Commit ab9d30cb by Chris Dodge

Merge branch 'master' of github.com:MITx/mitx into fix/cdodge/export-static-tabs

parents fc57e7af bc1452f2
...@@ -352,6 +352,33 @@ class ContentStoreTest(TestCase): ...@@ -352,6 +352,33 @@ class ContentStoreTest(TestCase):
def test_edit_unit_full(self): def test_edit_unit_full(self):
self.check_edit_unit('full') self.check_edit_unit('full')
def test_static_tab_reordering(self):
import_from_xml(modulestore(), 'common/test/data/', ['full'])
ms = modulestore('direct')
course = ms.get_item(Location(['i4x','edX','full','course','6.002_Spring_2012', None]))
# reverse the ordering
reverse_tabs = []
for tab in course.tabs:
if tab['type'] == 'static_tab':
reverse_tabs.insert(0, 'i4x://edX/full/static_tab/{0}'.format(tab['url_slug']))
resp = self.client.post(reverse('reorder_static_tabs'), json.dumps({'tabs':reverse_tabs}), "application/json")
course = ms.get_item(Location(['i4x','edX','full','course','6.002_Spring_2012', None]))
# compare to make sure that the tabs information is in the expected order after the server call
course_tabs = []
for tab in course.tabs:
if tab['type'] == 'static_tab':
course_tabs.append('i4x://edX/full/static_tab/{0}'.format(tab['url_slug']))
self.assertEqual(reverse_tabs, course_tabs)
def test_about_overrides(self): def test_about_overrides(self):
''' '''
This test case verifies that a course can use specialized override for about data, e.g. /about/Fall_2012/effort.html This test case verifies that a course can use specialized override for about data, e.g. /about/Fall_2012/effort.html
......
...@@ -903,6 +903,52 @@ def static_pages(request, org, course, coursename): ...@@ -903,6 +903,52 @@ def static_pages(request, org, course, coursename):
def edit_static(request, org, course, coursename): def edit_static(request, org, course, coursename):
return render_to_response('edit-static-page.html', {}) return render_to_response('edit-static-page.html', {})
@login_required
@expect_json
def reorder_static_tabs(request):
tabs = request.POST['tabs']
course = get_course_for_item(tabs[0])
if not has_access(request.user, course.location):
raise PermissionDenied()
# get list of existing static tabs in course
# make sure they are the same lengths (i.e. the number of passed in tabs equals the number
# that we know about) otherwise we can drop some!
existing_static_tabs = [t for t in course.tabs if t['type'] == 'static_tab']
if len(existing_static_tabs) != len(tabs):
return HttpResponseBadRequest()
# load all reference tabs, return BadRequest if we can't find any of them
tab_items =[]
for tab in tabs:
item = modulestore('direct').get_item(Location(tab))
if item is None:
return HttpResponseBadRequest()
tab_items.append(item)
# now just go through the existing course_tabs and re-order the static tabs
reordered_tabs = []
static_tab_idx = 0
for tab in course.tabs:
if tab['type'] == 'static_tab':
reordered_tabs.append({'type': 'static_tab',
'name' : tab_items[static_tab_idx].metadata.get('display_name'),
'url_slug' : tab_items[static_tab_idx].location.name})
static_tab_idx += 1
else:
reordered_tabs.append(tab)
# OK, re-assemble the static tabs in the new order
course.tabs = reordered_tabs
modulestore('direct').update_metadata(course.location, course.metadata)
return HttpResponse()
@login_required @login_required
@ensure_csrf_cookie @ensure_csrf_cookie
def edit_tabs(request, org, course, coursename): def edit_tabs(request, org, course, coursename):
...@@ -914,12 +960,19 @@ def edit_tabs(request, org, course, coursename): ...@@ -914,12 +960,19 @@ def edit_tabs(request, org, course, coursename):
if not has_access(request.user, location): if not has_access(request.user, location):
raise PermissionDenied() raise PermissionDenied()
static_tabs = modulestore('direct').get_items(static_tabs_loc)
# see tabs have been uninitialized (e.g. supporing courses created before tab support in studio) # see tabs have been uninitialized (e.g. supporing courses created before tab support in studio)
if course_item.tabs is None or len(course_item.tabs) == 0: if course_item.tabs is None or len(course_item.tabs) == 0:
initialize_course_tabs(course_item) initialize_course_tabs(course_item)
# first get all static tabs from the tabs list
# we do this because this is also the order in which items are displayed in the LMS
static_tabs_refs = [t for t in course_item.tabs if t['type'] == 'static_tab']
static_tabs = []
for static_tab_ref in static_tabs_refs:
static_tab_loc = Location(location)._replace(category='static_tab', name=static_tab_ref['url_slug'])
static_tabs.append(modulestore('direct').get_item(static_tab_loc))
components = [ components = [
static_tab.location.url() static_tab.location.url()
for static_tab for static_tab
...@@ -1326,7 +1379,6 @@ def import_course(request, org, course, name): ...@@ -1326,7 +1379,6 @@ def import_course(request, org, course, name):
@login_required @login_required
def generate_export_course(request, org, course, name): def generate_export_course(request, org, course, name):
location = ['i4x', org, course, 'course', name] location = ['i4x', org, course, 'course', name]
course_module = modulestore().get_item(location)
# check that logged in user has permissions to this item # check that logged in user has permissions to this item
if not has_access(request.user, location): if not has_access(request.user, location):
raise PermissionDenied() raise PermissionDenied()
...@@ -1373,3 +1425,10 @@ def export_course(request, org, course, name): ...@@ -1373,3 +1425,10 @@ def export_course(request, org, course, name):
'active_tab': 'export', 'active_tab': 'export',
'successful_import_redirect_url' : '' 'successful_import_redirect_url' : ''
}) })
def event(request):
'''
A noop to swallow the analytics call so that cms methods don't spook and poor developers looking at
console logs don't get distracted :-)
'''
return HttpResponse(True)
\ No newline at end of file
...@@ -15,7 +15,7 @@ class CMS.Views.TabsEdit extends Backbone.View ...@@ -15,7 +15,7 @@ class CMS.Views.TabsEdit extends Backbone.View
@$('.components').sortable( @$('.components').sortable(
handle: '.drag-handle' handle: '.drag-handle'
update: (event, ui) => alert 'not yet implemented!' update: @tabMoved
helper: 'clone' helper: 'clone'
opacity: '0.5' opacity: '0.5'
placeholder: 'component-placeholder' placeholder: 'component-placeholder'
...@@ -24,6 +24,20 @@ class CMS.Views.TabsEdit extends Backbone.View ...@@ -24,6 +24,20 @@ class CMS.Views.TabsEdit extends Backbone.View
items: '> .component' items: '> .component'
) )
tabMoved: (event, ui) =>
tabs = []
@$('.component').each((idx, element) =>
tabs.push($(element).data('id'))
)
$.ajax({
type:'POST',
url: '/reorder_static_tabs',
data: JSON.stringify({
tabs : tabs
}),
contentType: 'application/json'
})
addNewTab: (event) => addNewTab: (event) =>
event.preventDefault() event.preventDefault()
......
...@@ -17,6 +17,7 @@ urlpatterns = ('', ...@@ -17,6 +17,7 @@ urlpatterns = ('',
url(r'^publish_draft$', 'contentstore.views.publish_draft', name='publish_draft'), url(r'^publish_draft$', 'contentstore.views.publish_draft', name='publish_draft'),
url(r'^unpublish_unit$', 'contentstore.views.unpublish_unit', name='unpublish_unit'), url(r'^unpublish_unit$', 'contentstore.views.unpublish_unit', name='unpublish_unit'),
url(r'^create_new_course', 'contentstore.views.create_new_course', name='create_new_course'), url(r'^create_new_course', 'contentstore.views.create_new_course', name='create_new_course'),
url(r'^reorder_static_tabs', 'contentstore.views.reorder_static_tabs', name='reorder_static_tabs'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<name>[^/]+)$', url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course/(?P<name>[^/]+)$',
'contentstore.views.course_index', name='course_index'), 'contentstore.views.course_index', name='course_index'),
...@@ -67,6 +68,8 @@ urlpatterns = ('', ...@@ -67,6 +68,8 @@ urlpatterns = ('',
# temporary landing page for edge # temporary landing page for edge
url(r'^edge$', 'contentstore.views.edge', name='edge'), url(r'^edge$', 'contentstore.views.edge', name='edge'),
# noop to squelch ajax errors
url(r'^event$', 'contentstore.views.event', name='event'),
url(r'^heartbeat$', include('heartbeat.urls')), url(r'^heartbeat$', include('heartbeat.urls')),
) )
......
from optparse import make_option from optparse import make_option
from json import dump from json import dump
from datetime import datetime
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
...@@ -32,10 +33,9 @@ class Command(BaseCommand): ...@@ -32,10 +33,9 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
if len(args) < 1: if len(args) < 1:
raise CommandError("Missing single argument: output JSON file") outputfile = datetime.utcnow().strftime("pearson-dump-%Y%m%d-%H%M%S.json")
else:
# get output location: outputfile = args[0]
outputfile = args[0]
# construct the query object to dump: # construct the query object to dump:
registrations = TestCenterRegistration.objects.all() registrations = TestCenterRegistration.objects.all()
...@@ -65,6 +65,8 @@ class Command(BaseCommand): ...@@ -65,6 +65,8 @@ class Command(BaseCommand):
} }
if len(registration.upload_error_message) > 0: if len(registration.upload_error_message) > 0:
record['registration_error'] = registration.upload_error_message record['registration_error'] = registration.upload_error_message
if len(registration.testcenter_user.upload_error_message) > 0:
record['demographics_error'] = registration.testcenter_user.upload_error_message
if registration.needs_uploading: if registration.needs_uploading:
record['needs_uploading'] = True record['needs_uploading'] = True
...@@ -72,5 +74,5 @@ class Command(BaseCommand): ...@@ -72,5 +74,5 @@ class Command(BaseCommand):
# dump output: # dump output:
with open(outputfile, 'w') as outfile: with open(outputfile, 'w') as outfile:
dump(output, outfile) dump(output, outfile, indent=2)
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
{"type": "courseware"}, {"type": "courseware"},
{"type": "course_info", "name": "Course Info"}, {"type": "course_info", "name": "Course Info"},
{"type": "static_tab", "url_slug": "syllabus", "name": "Syllabus"}, {"type": "static_tab", "url_slug": "syllabus", "name": "Syllabus"},
{"type": "static_tab", "url_slug": "resources", "name": "Resources"},
{"type": "discussion", "name": "Discussion"}, {"type": "discussion", "name": "Discussion"},
{"type": "wiki", "name": "Wiki"}, {"type": "wiki", "name": "Wiki"},
{"type": "progress", "name": "Progress"} {"type": "progress", "name": "Progress"}
......
import factory
from student.models import (User, UserProfile, Registration,
CourseEnrollmentAllowed)
from django.contrib.auth.models import Group
from datetime import datetime
import uuid
class UserProfileFactory(factory.Factory):
FACTORY_FOR = UserProfile
user = None
name = 'Robot Studio'
courseware = 'course.xml'
class RegistrationFactory(factory.Factory):
FACTORY_FOR = Registration
user = None
activation_key = uuid.uuid4().hex
class UserFactory(factory.Factory):
FACTORY_FOR = User
username = 'robot'
email = 'robot@edx.org'
password = 'test'
first_name = 'Robot'
last_name = 'Tester'
is_staff = False
is_active = True
is_superuser = False
last_login = datetime.now()
date_joined = datetime.now()
class GroupFactory(factory.Factory):
FACTORY_FOR = Group
name = 'test_group'
class CourseEnrollmentAllowedFactory(factory.Factory):
FACTORY_FOR = CourseEnrollmentAllowed
email = 'test@edx.org'
course_id = 'edX/test/2012_Fall'
import unittest
import time
from mock import Mock
from django.test import TestCase
from xmodule.modulestore import Location
from factories import CourseEnrollmentAllowedFactory
import courseware.access as access
class AccessTestCase(TestCase):
def test__has_global_staff_access(self):
u = Mock(is_staff=False)
self.assertFalse(access._has_global_staff_access(u))
u = Mock(is_staff=True)
self.assertTrue(access._has_global_staff_access(u))
def test__has_access_to_location(self):
location = Location('i4x://edX/toy/course/2012_Fall')
self.assertFalse(access._has_access_to_location(None, location,
'staff', None))
u = Mock()
u.is_authenticated.return_value = False
self.assertFalse(access._has_access_to_location(u, location,
'staff', None))
u = Mock(is_staff=True)
self.assertTrue(access._has_access_to_location(u, location,
'instructor', None))
# A user has staff access if they are in the staff group
u = Mock(is_staff=False)
g = Mock()
g.name = 'staff_edX/toy/2012_Fall'
u.groups.all.return_value = [g]
self.assertTrue(access._has_access_to_location(u, location,
'staff', None))
# A user has staff access if they are in the instructor group
g.name = 'instructor_edX/toy/2012_Fall'
self.assertTrue(access._has_access_to_location(u, location,
'staff', None))
# A user has instructor access if they are in the instructor group
g.name = 'instructor_edX/toy/2012_Fall'
self.assertTrue(access._has_access_to_location(u, location,
'instructor', None))
# A user does not have staff access if they are
# not in either the staff or the the instructor group
g.name = 'student_only'
self.assertFalse(access._has_access_to_location(u, location,
'staff', None))
# A user does not have instructor access if they are
# not in the instructor group
g.name = 'student_only'
self.assertFalse(access._has_access_to_location(u, location,
'instructor', None))
def test__has_access_string(self):
u = Mock(is_staff=True)
self.assertFalse(access._has_access_string(u, 'not_global', 'staff', None))
u._has_global_staff_access.return_value = True
self.assertTrue(access._has_access_string(u, 'global', 'staff', None))
self.assertRaises(ValueError, access._has_access_string, u, 'global', 'not_staff', None)
def test__has_access_descriptor(self):
# TODO: override DISABLE_START_DATES and test the start date branch of the method
u = Mock()
d = Mock()
d.start = time.gmtime(time.time() - 86400) # make sure the start time is in the past
# Always returns true because DISABLE_START_DATES is set in test.py
self.assertTrue(access._has_access_descriptor(u, d, 'load'))
self.assertRaises(ValueError, access._has_access_descriptor, u, d, 'not_load_or_staff')
def test__has_access_course_desc_can_enroll(self):
u = Mock()
yesterday = time.gmtime(time.time() - 86400)
tomorrow = time.gmtime(time.time() + 86400)
c = Mock(enrollment_start=yesterday, enrollment_end=tomorrow)
c.metadata.get = 'is_public'
# User can enroll if it is between the start and end dates
self.assertTrue(access._has_access_course_desc(u, c, 'enroll'))
# User can enroll if authenticated and specifically allowed for that course
# even outside the open enrollment period
u = Mock(email='test@edx.org', is_staff=False)
u.is_authenticated.return_value = True
c = Mock(enrollment_start=tomorrow, enrollment_end=tomorrow, id='edX/test/2012_Fall')
c.metadata.get = 'is_public'
allowed = CourseEnrollmentAllowedFactory(email=u.email, course_id=c.id)
self.assertTrue(access._has_access_course_desc(u, c, 'enroll'))
# Staff can always enroll even outside the open enrollment period
u = Mock(email='test@edx.org', is_staff=True)
u.is_authenticated.return_value = True
c = Mock(enrollment_start=tomorrow, enrollment_end=tomorrow, id='edX/test/Whenever')
c.metadata.get = 'is_public'
self.assertTrue(access._has_access_course_desc(u, c, 'enroll'))
# TODO:
# Non-staff cannot enroll outside the open enrollment period if not specifically allowed
...@@ -6,7 +6,16 @@ ...@@ -6,7 +6,16 @@
<link type="text/html" rel="alternate" href="http://blog.edx.org/"/> <link type="text/html" rel="alternate" href="http://blog.edx.org/"/>
##<link type="application/atom+xml" rel="self" href="https://github.com/blog.atom"/> ##<link type="application/atom+xml" rel="self" href="https://github.com/blog.atom"/>
<title>EdX Blog</title> <title>EdX Blog</title>
<updated>2013-01-21T14:00:12-07:00</updated> <updated>2013-01-30T14:00:12-07:00</updated>
<entry>
<id>tag:www.edx.org,2012:Post/13</id>
<published>2013-01-30T10:00:00-07:00</published>
<updated>2013-01-30T10:00:00-07:00</updated>
<link type="text/html" rel="alternate" href="${reverse('press/eric-lander-secret-of-life')}"/>
<title>New biology course from human genome pioneer Eric Lander</title>
<content type="html">&lt;img src=&quot;${static.url('images/press/releases/eric-lander_240x180.jpg')}&quot; /&gt;
&lt;p&gt;&lt;/p&gt;</content>
</entry>
<entry> <entry>
<id>tag:www.edx.org,2012:Post/12</id> <id>tag:www.edx.org,2012:Post/12</id>
<published>2013-01-29T10:00:00-07:00</published> <published>2013-01-29T10:00:00-07:00</published>
......
...@@ -39,7 +39,14 @@ ...@@ -39,7 +39,14 @@
</article> </article>
<article class="response"> <article class="response">
<h3>Will certificates be awarded?</h3> <h3>Will certificates be awarded?</h3>
<p>Yes. Online learners who demonstrate mastery of subjects can earn a certificate of mastery. Certificates will be issued by edX under the name of the underlying "X University" from where the course originated, i.e. HarvardX, <em>MITx</em> or BerkeleyX. For the courses in Fall 2012, those certificates will be free. There is a plan to charge a modest fee for certificates in the future.</p> <p>Yes. Online learners who demonstrate mastery of subjects can earn a certificate
of mastery. Certificates will be issued at the discretion of edX and the underlying
X University that offered the course under the name of the underlying "X
University" from where the course originated, i.e. HarvardX, MITx or BerkeleyX.
For the courses in Fall 2012, those certificates will be free. There is a plan to
charge a modest fee for certificates in the future. Note: At this time, edX is
holding certificates for learners connected with Cuba, Iran, Syria and Sudan
pending confirmation that the issuance is in compliance with U.S. embargoes.</p>
</article> </article>
<article class="response"> <article class="response">
<h3>What will the scope of the online courses be? How many? Which faculty?</h3> <h3>What will the scope of the online courses be? How many? Which faculty?</h3>
......
...@@ -180,8 +180,17 @@ ...@@ -180,8 +180,17 @@
<article class="response"> <article class="response">
<h3 class="question">Will I get a certificate for taking an edX course?</h3> <h3 class="question">Will I get a certificate for taking an edX course?</h3>
<div class="answer" id="certificates_and_credits_faq_answer_0"> <div class ="answer" id="certificates_and_credits_faq_answer_0">
<p>Online learners who receive a passing grade for a course will receive a certificate of mastery from edX and the underlying X University that offered the course. For example, a certificate of mastery for MITx’s 6.002x Circuits & Electronics will come from edX and MITx.</p> <p>Online learners who receive a passing grade for a course will receive a certificate
of mastery at the discretion of edX and the underlying X University that offered
the course. For example, a certificate of mastery for MITx’s 6.002x Circuits &amp;
Electronics will come from edX and MITx.</p>
<p>If you passed the course, your certificate of mastery will be delivered online
through edx.org. So be sure to check your email in the weeks following the final
grading – you will be able to download and print your certificate. Note: At this
time, edX is holding certificates for learners connected with Cuba, Iran, Syria
and Sudan pending confirmation that the issuance is in compliance with U.S.
embargoes.</p>
</div> </div>
</article> </article>
<article class="response"> <article class="response">
......
<%! from django.core.urlresolvers import reverse %>
<%inherit file="../../main.html" />
<%namespace name='static' file='../../static_content.html'/>
<%block name="title"><title>Human Genome Pioneer Eric Lander to reveal “the secret of life”</title></%block>
<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<section class="pressrelease">
<section class="container">
<h1>Human Genome Pioneer Eric Lander to reveal “the secret of life”</h1>
<hr class="horizontal-divider">
<article>
<h2>Broad Institute Director shares his MIT introductory biology course, covering topics in biochemistry, genetics and genomics, through edX.</h2>
<figure>
<a href="${static.url('images/press/releases/eric-lander-lab.jpg')}"><img src="${static.url('images/press/releases/eric-lander-lab_x300.jpg')}" /></a>
<figcaption>
<p>Eric Lander, the founding director of the Broad Institute and a professor at MIT and Harvard Medical School.</p>
<a href="${static.url('images/press/releases/eric-lander-lab.jpg')}">High Resolution Image</a></p>
</figcaption>
</figure>
<p><strong>CAMBRIDGE, MA &ndash; January 30, 2013 &ndash;</strong>
In the past 10 years, the ability to decode or “sequence” DNA has grown by a million-fold, a stunning rate of progress that is producing a flood of information about human biology and disease. Because of these advances, the scientific community — and the world as a whole — stands on the verge of a revolution in biology. In the coming decades scientists will be able to understand how cells are “wired” and how that wiring is disrupted in human diseases ranging from diabetes to cancer to schizophrenia. Now, with his free online course, <a href="https://www.edx.org/courses/MITx/7.00x/2013_Spring/about">7.00x Introductory Biology: “The Secret of Life”</a>, genome pioneer Eric Lander, the founding director of the Broad Institute and a professor at MIT and Harvard Medical School, will explain to students around the world the basics of biology – the secret of life, so to speak – so that they can understand today’s revolution in biology.</p>
<p><a href="https://www.edx.org/">EdX</a>, the not-for-profit online learning initiative founded by Harvard University and the Massachusetts Institute of Technology (MIT), brings the best courses from the best faculty at the best institutions to anyone with an Internet connection. For the past 20 years, legendary teacher Lander has taught Introductory Biology to more than half of all MIT students. He has now adapted his course for online education, creating the newest course on the edX platform. The course, 7.00X, is now open for enrollment, with the first class slated for March 5th. This course will include innovative technology including a 3D molecule viewer and gene explorer tool to transform the learning experience. It is open to all levels and types of learners.</p>
<p>“Introducing the freshman class of MIT to the basics of biology is exhilarating,” said Lander. “Now, with this edX course, I look forward to teaching people around the world. There are no prerequisites for this course – other than curiosity and an interest in understanding some of the greatest scientific challenges of our time.”</p>
<p>Those taking the course will learn the fundamental ideas that underlie modern biology and medicine, including genetics, biochemistry, molecular biology, recombinant DNA, genomics and genomic medicine. They will become familiar with the structure and function of macromolecules such as DNA, RNA and proteins and understand how information flows within cells. Students will explore how mutations affect biological function and cause human disease. They will learn about modern molecular biological techniques and their wide-ranging impact.</p>
<p>“Eric Lander has created this remarkable digitally enhanced introduction to genetics and biology,” said Anant Agarwal, President of edX. “With this unique online version, he has brought the introductory biology course to a new level. It has been completely rethought and retooled, incorporating cutting-edge online interactive tools as well as community-building contests and milestone-based prizes.”</p>
<p>With online courses through edX like 7.00x, what matters isn’t what people have achieved or their transcripts, but their desire to learn. Students only need to come with a real interest in science and the desire to understand what's going on at the forefront of biology, and to learn the fundamental principles on which an amazing biomedical revolution is based – from one of the top scientist in the world. <a href="https://www.edx.org/courses/MITx/7.00x/2013_Spring/about">7.00x Introductory Biology: The Secret of Life</a> is now available for enrollment. Classes will start on March 5, 2013.</p>
<p>Dr. Eric Lander is President and Founding Director of the Broad Institute of Harvard and MIT, a new kind of collaborative biomedical research institution focused on genomic medicine. Dr. Lander is also Professor of Biology at MIT and Professor of Systems Biology at the Harvard Medical School. In addition, Dr. Lander serves as Co-Chair of the President’s Council of Advisors on Science and Technology, which advises the White House on science and technology. A geneticist, molecular biologist and mathematician, Dr. Lander has played a pioneering role in all aspects of the reading, understanding and medical application of the human genome. He was a principal leader of the international Human Genome Project (HGP) from 1990-2003, with his group being the largest contributor to the mapping and sequencing of the human genetic blueprint. Dr. Lander was an early pioneer in the free availability of genomic tools and information. Finally, he has mentored an extraordinary cadre of young scientists who have become the next generation of leaders in medical genomics. The recipient of numerous awards and honorary degrees, Dr. Lander was elected a member of the U.S. National Academy of Sciences in 1997 and of the U.S. Institute of Medicine in 1999.</p>
<p>Previously announced new 2013 courses include:
<a href="https://www.edx.org/courses/MITx/8.02x/2013_Spring/about">8.02x Electricity and Magnetism from Walter Lewin</a>
<a href="http://www.edx.org/courses/HarvardX/ER22x/2013_Spring/about">Justice from Michael Sandel</a>; <a href="http://www.edx.org/courses/BerkeleyX/Stat2.1x/2013_Spring/about">Introduction to Statistics from Ani Adhikari</a>; <a href="http://www.edx.org/courses/MITx/14.73x/2013_Spring/about">The Challenges of Global Poverty from Esther Duflo</a>; <a href="http://www.edx.org/courses/HarvardX/CB22x/2013_Spring/about">The Ancient Greek Hero from Gregory Nagy</a>; <a href="https://www.edx.org/courses/BerkeleyX/CS191x/2013_Spring/about">Quantum Mechanics and Quantum Computation from Umesh Vazirani</a>; <a href="https://www.edx.org/courses/HarvardX/PH278x/2013_Spring/about">Human Health and Global Environmental Change, from Aaron Bernstein and Jack Spengler</a>.</p>
<p>In addition to these new courses, edX is bringing back several courses from the popular fall 2012 semester: <a href="http://www.edx.org/courses/MITx/6.00x/2013_Spring/about">Introduction to Computer Science and Programming</a>; <a href="http://www.edx.org/courses/MITx/3.091x/2013_Spring/about">Introduction to Solid State Chemistry</a>; <a href="http://www.edx.org/courses/BerkeleyX/CS188.1x/2013_Spring/about">Introduction to Artificial Intelligence</a>; <a href="https://www.edx.org/courses/BerkeleyX/CS169.1x/2013_Spring/about">Software as a Service I</a>; <a href="https://www.edx.org/courses/BerkeleyX/CS169.2x/2013_Spring/about">Software as a Service II</a>; <a href="http://www.edx.org/courses/BerkeleyX/CS184.1x/2013_Spring/about">Foundations of Computer Graphics</a>.</p>
<h2>About the Broad Institute of MIT and Harvard</h2>
<p>The Eli and Edythe L. Broad Institute of MIT and Harvard was founded in 2003 to empower this generation of creative scientists to transform medicine with new genome-based knowledge. The Broad Institute seeks to describe all the molecular components of life and their connections; discover the molecular basis of major human diseases; develop effective new approaches to diagnostics and therapeutics; and disseminate discoveries, tools, methods and data openly to the entire scientific community.</p>
<p>Founded by MIT, Harvard and its affiliated hospitals, and the visionary Los Angeles philanthropists Eli and Edythe L. Broad, the Broad Institute includes faculty, professional staff and students from throughout the MIT and Harvard biomedical research communities and beyond, with collaborations spanning over a hundred private and public institutions in more than 40 countries worldwide. For further information about the Broad Institute, go to <a href="http://www.broadinstitute.org">www.broadinstitute.org</a>.</p>
<h2>About edX</h2>
<p><a href="https://www.edx.org/">EdX</a> is a not-for-profit enterprise of its founding partners <a href="http://www.harvard.edu">Harvard University</a> and the <a href="http://www.mit.edu">Massachusetts Institute of Technology</a> focused on transforming online and on-campus learning through groundbreaking methodologies, game-like experiences and cutting-edge research. EdX provides inspirational and transformative knowledge to students of all ages, social status, and income who form worldwide communities of learners. EdX uses its open source technology to transcend physical and social borders. We’re focused on people, not profit. EdX is based in Cambridge, Massachusetts in the USA.</p>
<section class="contact">
<p><strong>Contact:</strong></p>
<p>Brad Baker, Weber Shandwick for edX</p>
<p>BBaker@webershandwick.com</p>
<p>(617) 520-7043</p>
</section>
<section class="footer">
<hr class="horizontal-divider">
<div class="logo"></div><h3 class="date">01 - 30 - 2013</h3>
<div class="social-sharing">
<hr class="horizontal-divider">
<p>Share with friends and family:</p>
<a href="http://twitter.com/intent/tweet?text=:Human+Genome+Pioneer+Eric+Lander+to+reveal+the+secret+of+life
+http://www.edx.org/press/eric-lander-secret-of-life" class="share">
<img src="${static.url('images/social/twitter-sharing.png')}">
</a>
</a>
<a href="mailto:?subject=Human%20Genome%20Pioneer%20Eric%20Lander%20to%20reveal%20the%20secret%20of%20life…http://edx.org/press/eric-lander-secret-of-life" class="share">
<img src="${static.url('images/social/email-sharing.png')}">
</a>
<div class="fb-like" data-href="http://edx.org/press/eric-lander-secret-of-life" data-send="true" data-width="450" data-show-faces="true"></div>
</div>
</section>
</article>
</section>
</section>
<%! from django.core.urlresolvers import reverse %>
<%inherit file="../../main.html" />
<%namespace name='static' file='../../static_content.html'/>
<%block name="title"><title>TITLE</title></%block>
<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<section class="pressrelease">
<section class="container">
<h1>TITLE</h1>
<hr class="horizontal-divider">
<article>
<h2>SUBTITLE</h2>
<p><strong>CAMBRIDGE, MA &ndash; MONTH DAY, YEAR &ndash;</strong>
Text</p>
<p>more text</p>
<h2>About edX</h2>
<p><a href="https://www.edx.org/">EdX</a> is a not-for-profit enterprise of its founding partners <a href="http://www.harvard.edu">Harvard University</a> and the <a href="http://www.mit.edu">Massachusetts Institute of Technology</a> focused on transforming online and on-campus learning through groundbreaking methodologies, game-like experiences and cutting-edge research. EdX provides inspirational and transformative knowledge to students of all ages, social status, and income who form worldwide communities of learners. EdX uses its open source technology to transcend physical and social borders. We’re focused on people, not profit. EdX is based in Cambridge, Massachusetts in the USA.</p>
<section class="contact">
<p><strong>Contact:</strong></p>
<p>Brad Baker, Weber Shandwick for edX</p>
<p>BBaker@webershandwick.com</p>
<p>(617) 520-7043</p>
</section>
<section class="footer">
<hr class="horizontal-divider">
<div class="logo"></div><h3 class="date">DATE: 01 - 29 - 2013</h3>
<div class="social-sharing">
<hr class="horizontal-divider">
<p>Share with friends and family:</p>
<a href="http://twitter.com/intent/tweet?text=:BLAH+BLAH+BLAH+http://www.edx.org/press/LINK" class="share">
<img src="${static.url('images/social/twitter-sharing.png')}">
</a>
</a>
<a href="mailto:?subject=BLAH%BLAH%BLAH…http://edx.org/press/LINK" class="share">
<img src="${static.url('images/social/email-sharing.png')}">
</a>
<div class="fb-like" data-href="http://edx.org/press/LINK" data-send="true" data-width="450" data-show-faces="true"></div>
</div>
</section>
</article>
</section>
</section>
...@@ -125,11 +125,14 @@ urlpatterns = ('', ...@@ -125,11 +125,14 @@ urlpatterns = ('',
url(r'^press/bostonx-announcement$', 'static_template_view.views.render', url(r'^press/bostonx-announcement$', 'static_template_view.views.render',
{'template': 'press_releases/bostonx_announcement.html'}, {'template': 'press_releases/bostonx_announcement.html'},
name="press/bostonx-announcement"), name="press/bostonx-announcement"),
url(r'^press/eric-lander-secret-of-life$', 'static_template_view.views.render',
{'template': 'press_releases/eric_lander_secret_of_life.html'},
name="press/eric-lander-secret-of-life"),
# Should this always update to point to the latest press release? # Should this always update to point to the latest press release?
(r'^pressrelease$', 'django.views.generic.simple.redirect_to', (r'^pressrelease$', 'django.views.generic.simple.redirect_to',
{'url': '/press/bostonx-announcement'}), {'url': '/press/eric-lander-secret-of-life'}),
(r'^favicon\.ico$', 'django.views.generic.simple.redirect_to', {'url': '/static/images/favicon.ico'}), (r'^favicon\.ico$', 'django.views.generic.simple.redirect_to', {'url': '/static/images/favicon.ico'}),
......
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