Merge branch 'master' of github.com:MITx/mitx into fix/cdodge/studio-forum-improvements
This commit is contained in:
@@ -165,7 +165,7 @@ def grade(student, request, course, model_data_cache=None, keep_raw_scores=False
|
||||
# Create a fake key to pull out a StudentModule object from the ModelDataCache
|
||||
|
||||
key = LmsKeyValueStore.Key(
|
||||
Scope.student_state,
|
||||
Scope.user_state,
|
||||
student.id,
|
||||
moduledescriptor.location,
|
||||
None
|
||||
@@ -370,7 +370,7 @@ def get_score(course_id, user, problem_descriptor, module_creator, model_data_ca
|
||||
|
||||
# Create a fake KeyValueStore key to pull out the StudentModule
|
||||
key = LmsKeyValueStore.Key(
|
||||
Scope.student_state,
|
||||
Scope.user_state,
|
||||
user.id,
|
||||
problem_descriptor.location,
|
||||
None
|
||||
|
||||
@@ -76,6 +76,11 @@ class Command(BaseCommand):
|
||||
for hist_module in hist_modules:
|
||||
self.remove_studentmodulehistory_input_state(hist_module, save_changes)
|
||||
|
||||
if self.num_visited % 1000 == 0:
|
||||
LOG.info(" Progress: updated {0} of {1} student modules".format(self.num_changed, self.num_visited))
|
||||
LOG.info(" Progress: updated {0} of {1} student history modules".format(self.num_hist_changed,
|
||||
self.num_hist_visited))
|
||||
|
||||
@transaction.autocommit
|
||||
def remove_studentmodule_input_state(self, module, save_changes):
|
||||
''' Fix the grade assigned to a StudentModule'''
|
||||
|
||||
@@ -134,7 +134,7 @@ class ModelDataCache(object):
|
||||
"""
|
||||
if scope in (Scope.children, Scope.parent):
|
||||
return []
|
||||
elif scope == Scope.student_state:
|
||||
elif scope == Scope.user_state:
|
||||
return self._chunked_query(
|
||||
StudentModule,
|
||||
'module_state_key__in',
|
||||
@@ -159,7 +159,7 @@ class ModelDataCache(object):
|
||||
),
|
||||
field_name__in=set(field.name for field in fields),
|
||||
)
|
||||
elif scope == Scope.student_preferences:
|
||||
elif scope == Scope.preferences:
|
||||
return self._chunked_query(
|
||||
XModuleStudentPrefsField,
|
||||
'module_type__in',
|
||||
@@ -167,7 +167,7 @@ class ModelDataCache(object):
|
||||
student=self.user.pk,
|
||||
field_name__in=set(field.name for field in fields),
|
||||
)
|
||||
elif scope == Scope.student_info:
|
||||
elif scope == Scope.user_info:
|
||||
return self._query(
|
||||
XModuleStudentInfoField,
|
||||
student=self.user.pk,
|
||||
@@ -190,15 +190,15 @@ class ModelDataCache(object):
|
||||
"""
|
||||
Return the key used in the ModelDataCache for the specified KeyValueStore key
|
||||
"""
|
||||
if key.scope == Scope.student_state:
|
||||
if key.scope == Scope.user_state:
|
||||
return (key.scope, key.block_scope_id.url())
|
||||
elif key.scope == Scope.content:
|
||||
return (key.scope, key.block_scope_id.url(), key.field_name)
|
||||
elif key.scope == Scope.settings:
|
||||
return (key.scope, '%s-%s' % (self.course_id, key.block_scope_id.url()), key.field_name)
|
||||
elif key.scope == Scope.student_preferences:
|
||||
elif key.scope == Scope.preferences:
|
||||
return (key.scope, key.block_scope_id, key.field_name)
|
||||
elif key.scope == Scope.student_info:
|
||||
elif key.scope == Scope.user_info:
|
||||
return (key.scope, key.field_name)
|
||||
|
||||
def _cache_key_from_field_object(self, scope, field_object):
|
||||
@@ -206,15 +206,15 @@ class ModelDataCache(object):
|
||||
Return the key used in the ModelDataCache for the specified scope and
|
||||
field
|
||||
"""
|
||||
if scope == Scope.student_state:
|
||||
if scope == Scope.user_state:
|
||||
return (scope, field_object.module_state_key)
|
||||
elif scope == Scope.content:
|
||||
return (scope, field_object.definition_id, field_object.field_name)
|
||||
elif scope == Scope.settings:
|
||||
return (scope, field_object.usage_id, field_object.field_name)
|
||||
elif scope == Scope.student_preferences:
|
||||
elif scope == Scope.preferences:
|
||||
return (scope, field_object.module_type, field_object.field_name)
|
||||
elif scope == Scope.student_info:
|
||||
elif scope == Scope.user_info:
|
||||
return (scope, field_object.field_name)
|
||||
|
||||
def find(self, key):
|
||||
@@ -237,13 +237,14 @@ class ModelDataCache(object):
|
||||
if field_object is not None:
|
||||
return field_object
|
||||
|
||||
if key.scope == Scope.student_state:
|
||||
if key.scope == Scope.user_state:
|
||||
field_object, _ = StudentModule.objects.get_or_create(
|
||||
course_id=self.course_id,
|
||||
student=self.user,
|
||||
module_type=key.block_scope_id.category,
|
||||
module_state_key=key.block_scope_id.url(),
|
||||
defaults={'state': json.dumps({})},
|
||||
defaults={'state': json.dumps({}),
|
||||
'module_type': key.block_scope_id.category,
|
||||
},
|
||||
)
|
||||
elif key.scope == Scope.content:
|
||||
field_object, _ = XModuleContentField.objects.get_or_create(
|
||||
@@ -255,13 +256,13 @@ class ModelDataCache(object):
|
||||
field_name=key.field_name,
|
||||
usage_id='%s-%s' % (self.course_id, key.block_scope_id.url()),
|
||||
)
|
||||
elif key.scope == Scope.student_preferences:
|
||||
elif key.scope == Scope.preferences:
|
||||
field_object, _ = XModuleStudentPrefsField.objects.get_or_create(
|
||||
field_name=key.field_name,
|
||||
module_type=key.block_scope_id,
|
||||
student=self.user,
|
||||
)
|
||||
elif key.scope == Scope.student_info:
|
||||
elif key.scope == Scope.user_info:
|
||||
field_object, _ = XModuleStudentInfoField.objects.get_or_create(
|
||||
field_name=key.field_name,
|
||||
student=self.user,
|
||||
@@ -281,12 +282,12 @@ class LmsKeyValueStore(KeyValueStore):
|
||||
If the scope to write to is not one of the 5 named scopes:
|
||||
Scope.content
|
||||
Scope.settings
|
||||
Scope.student_state
|
||||
Scope.student_preferences
|
||||
Scope.student_info
|
||||
Scope.user_state
|
||||
Scope.preferences
|
||||
Scope.user_info
|
||||
then an InvalidScopeError will be raised.
|
||||
|
||||
Data for Scope.student_state is stored as StudentModule objects via the django orm.
|
||||
Data for Scope.user_state is stored as StudentModule objects via the django orm.
|
||||
|
||||
Data for the other scopes is stored in individual objects that are named for the
|
||||
scope involved and have the field name as a key
|
||||
@@ -297,9 +298,9 @@ class LmsKeyValueStore(KeyValueStore):
|
||||
_allowed_scopes = (
|
||||
Scope.content,
|
||||
Scope.settings,
|
||||
Scope.student_state,
|
||||
Scope.student_preferences,
|
||||
Scope.student_info,
|
||||
Scope.user_state,
|
||||
Scope.preferences,
|
||||
Scope.user_info,
|
||||
Scope.children,
|
||||
)
|
||||
|
||||
@@ -321,7 +322,7 @@ class LmsKeyValueStore(KeyValueStore):
|
||||
if field_object is None:
|
||||
raise KeyError(key.field_name)
|
||||
|
||||
if key.scope == Scope.student_state:
|
||||
if key.scope == Scope.user_state:
|
||||
return json.loads(field_object.state)[key.field_name]
|
||||
else:
|
||||
return json.loads(field_object.value)
|
||||
@@ -335,7 +336,7 @@ class LmsKeyValueStore(KeyValueStore):
|
||||
if key.scope not in self._allowed_scopes:
|
||||
raise InvalidScopeError(key.scope)
|
||||
|
||||
if key.scope == Scope.student_state:
|
||||
if key.scope == Scope.user_state:
|
||||
state = json.loads(field_object.state)
|
||||
state[key.field_name] = value
|
||||
field_object.state = json.dumps(state)
|
||||
@@ -355,7 +356,7 @@ class LmsKeyValueStore(KeyValueStore):
|
||||
if field_object is None:
|
||||
raise KeyError(key.field_name)
|
||||
|
||||
if key.scope == Scope.student_state:
|
||||
if key.scope == Scope.user_state:
|
||||
state = json.loads(field_object.state)
|
||||
del state[key.field_name]
|
||||
field_object.state = json.dumps(state)
|
||||
@@ -377,7 +378,7 @@ class LmsKeyValueStore(KeyValueStore):
|
||||
if field_object is None:
|
||||
return False
|
||||
|
||||
if key.scope == Scope.student_state:
|
||||
if key.scope == Scope.user_state:
|
||||
return key.field_name in json.loads(field_object.state)
|
||||
else:
|
||||
return True
|
||||
|
||||
@@ -165,7 +165,7 @@ class XModuleSettingsField(models.Model):
|
||||
|
||||
class XModuleStudentPrefsField(models.Model):
|
||||
"""
|
||||
Stores data set in the Scope.student_preferences scope by an xmodule field
|
||||
Stores data set in the Scope.preferences scope by an xmodule field
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
@@ -199,7 +199,7 @@ class XModuleStudentPrefsField(models.Model):
|
||||
|
||||
class XModuleStudentInfoField(models.Model):
|
||||
"""
|
||||
Stores data set in the Scope.student_preferences scope by an xmodule field
|
||||
Stores data set in the Scope.preferences scope by an xmodule field
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -177,18 +177,13 @@ def get_module_for_descriptor(user, request, descriptor, model_data_cache, cours
|
||||
# Intended use is as {ajax_url}/{dispatch_command}, so get rid of the trailing slash.
|
||||
ajax_url = ajax_url.rstrip('/')
|
||||
|
||||
# Fully qualified callback URL for external queueing system
|
||||
xqueue_callback_url = '{proto}://{host}'.format(
|
||||
host=request.get_host(),
|
||||
proto=request.META.get('HTTP_X_FORWARDED_PROTO', 'https' if request.is_secure() else 'http')
|
||||
)
|
||||
|
||||
def make_xqueue_callback(dispatch='score_update'):
|
||||
# Fully qualified callback URL for external queueing system
|
||||
xqueue_callback_url = '{proto}://{host}'.format(
|
||||
host=request.get_host(),
|
||||
proto=request.META.get('HTTP_X_FORWARDED_PROTO', 'https' if request.is_secure() else 'http')
|
||||
)
|
||||
xqueue_callback_url = settings.XQUEUE_INTERFACE.get('callback_url',xqueue_callback_url) # allow override
|
||||
|
||||
xqueue_callback_url += reverse('xqueue_callback',
|
||||
kwargs=dict(course_id=course_id,
|
||||
|
||||
@@ -32,9 +32,9 @@ course_id = 'edX/test_course/test'
|
||||
|
||||
content_key = partial(LmsKeyValueStore.Key, Scope.content, None, location('def_id'))
|
||||
settings_key = partial(LmsKeyValueStore.Key, Scope.settings, None, location('def_id'))
|
||||
student_state_key = partial(LmsKeyValueStore.Key, Scope.student_state, 'user', location('def_id'))
|
||||
student_prefs_key = partial(LmsKeyValueStore.Key, Scope.student_preferences, 'user', 'problem')
|
||||
student_info_key = partial(LmsKeyValueStore.Key, Scope.student_info, 'user', None)
|
||||
user_state_key = partial(LmsKeyValueStore.Key, Scope.user_state, 'user', location('def_id'))
|
||||
prefs_key = partial(LmsKeyValueStore.Key, Scope.preferences, 'user', 'problem')
|
||||
user_info_key = partial(LmsKeyValueStore.Key, Scope.user_info, 'user', None)
|
||||
|
||||
|
||||
class UserFactory(factory.Factory):
|
||||
@@ -115,13 +115,13 @@ class TestInvalidScopes(TestCase):
|
||||
def setUp(self):
|
||||
self.desc_md = {}
|
||||
self.user = UserFactory.create()
|
||||
self.mdc = ModelDataCache([mock_descriptor([mock_field(Scope.student_state, 'a_field')])], course_id, self.user)
|
||||
self.mdc = ModelDataCache([mock_descriptor([mock_field(Scope.user_state, 'a_field')])], course_id, self.user)
|
||||
self.kvs = LmsKeyValueStore(self.desc_md, self.mdc)
|
||||
|
||||
def test_invalid_scopes(self):
|
||||
for scope in (Scope(student=True, block=BlockScope.DEFINITION),
|
||||
Scope(student=False, block=BlockScope.TYPE),
|
||||
Scope(student=False, block=BlockScope.ALL)):
|
||||
for scope in (Scope(user=True, block=BlockScope.DEFINITION),
|
||||
Scope(user=False, block=BlockScope.TYPE),
|
||||
Scope(user=False, block=BlockScope.ALL)):
|
||||
self.assertRaises(InvalidScopeError, self.kvs.get, LmsKeyValueStore.Key(scope, None, None, 'field'))
|
||||
self.assertRaises(InvalidScopeError, self.kvs.set, LmsKeyValueStore.Key(scope, None, None, 'field'), 'value')
|
||||
self.assertRaises(InvalidScopeError, self.kvs.delete, LmsKeyValueStore.Key(scope, None, None, 'field'))
|
||||
@@ -134,48 +134,48 @@ class TestStudentModuleStorage(TestCase):
|
||||
self.desc_md = {}
|
||||
student_module = StudentModuleFactory(state=json.dumps({'a_field': 'a_value'}))
|
||||
self.user = student_module.student
|
||||
self.mdc = ModelDataCache([mock_descriptor([mock_field(Scope.student_state, 'a_field')])], course_id, self.user)
|
||||
self.mdc = ModelDataCache([mock_descriptor([mock_field(Scope.user_state, 'a_field')])], course_id, self.user)
|
||||
self.kvs = LmsKeyValueStore(self.desc_md, self.mdc)
|
||||
|
||||
def test_get_existing_field(self):
|
||||
"Test that getting an existing field in an existing StudentModule works"
|
||||
self.assertEquals('a_value', self.kvs.get(student_state_key('a_field')))
|
||||
self.assertEquals('a_value', self.kvs.get(user_state_key('a_field')))
|
||||
|
||||
def test_get_missing_field(self):
|
||||
"Test that getting a missing field from an existing StudentModule raises a KeyError"
|
||||
self.assertRaises(KeyError, self.kvs.get, student_state_key('not_a_field'))
|
||||
self.assertRaises(KeyError, self.kvs.get, user_state_key('not_a_field'))
|
||||
|
||||
def test_set_existing_field(self):
|
||||
"Test that setting an existing student_state field changes the value"
|
||||
self.kvs.set(student_state_key('a_field'), 'new_value')
|
||||
"Test that setting an existing user_state field changes the value"
|
||||
self.kvs.set(user_state_key('a_field'), 'new_value')
|
||||
self.assertEquals(1, StudentModule.objects.all().count())
|
||||
self.assertEquals({'a_field': 'new_value'}, json.loads(StudentModule.objects.all()[0].state))
|
||||
|
||||
def test_set_missing_field(self):
|
||||
"Test that setting a new student_state field changes the value"
|
||||
self.kvs.set(student_state_key('not_a_field'), 'new_value')
|
||||
"Test that setting a new user_state field changes the value"
|
||||
self.kvs.set(user_state_key('not_a_field'), 'new_value')
|
||||
self.assertEquals(1, StudentModule.objects.all().count())
|
||||
self.assertEquals({'a_field': 'a_value', 'not_a_field': 'new_value'}, json.loads(StudentModule.objects.all()[0].state))
|
||||
|
||||
def test_delete_existing_field(self):
|
||||
"Test that deleting an existing field removes it from the StudentModule"
|
||||
self.kvs.delete(student_state_key('a_field'))
|
||||
self.kvs.delete(user_state_key('a_field'))
|
||||
self.assertEquals(1, StudentModule.objects.all().count())
|
||||
self.assertRaises(KeyError, self.kvs.get, student_state_key('not_a_field'))
|
||||
self.assertRaises(KeyError, self.kvs.get, user_state_key('not_a_field'))
|
||||
|
||||
def test_delete_missing_field(self):
|
||||
"Test that deleting a missing field from an existing StudentModule raises a KeyError"
|
||||
self.assertRaises(KeyError, self.kvs.delete, student_state_key('not_a_field'))
|
||||
self.assertRaises(KeyError, self.kvs.delete, user_state_key('not_a_field'))
|
||||
self.assertEquals(1, StudentModule.objects.all().count())
|
||||
self.assertEquals({'a_field': 'a_value'}, json.loads(StudentModule.objects.all()[0].state))
|
||||
|
||||
def test_has_existing_field(self):
|
||||
"Test that `has` returns True for existing fields in StudentModules"
|
||||
self.assertTrue(self.kvs.has(student_state_key('a_field')))
|
||||
self.assertTrue(self.kvs.has(user_state_key('a_field')))
|
||||
|
||||
def test_has_missing_field(self):
|
||||
"Test that `has` returns False for missing fields in StudentModule"
|
||||
self.assertFalse(self.kvs.has(student_state_key('not_a_field')))
|
||||
self.assertFalse(self.kvs.has(user_state_key('not_a_field')))
|
||||
|
||||
|
||||
class TestMissingStudentModule(TestCase):
|
||||
@@ -187,14 +187,14 @@ class TestMissingStudentModule(TestCase):
|
||||
|
||||
def test_get_field_from_missing_student_module(self):
|
||||
"Test that getting a field from a missing StudentModule raises a KeyError"
|
||||
self.assertRaises(KeyError, self.kvs.get, student_state_key('a_field'))
|
||||
self.assertRaises(KeyError, self.kvs.get, user_state_key('a_field'))
|
||||
|
||||
def test_set_field_in_missing_student_module(self):
|
||||
"Test that setting a field in a missing StudentModule creates the student module"
|
||||
self.assertEquals(0, len(self.mdc.cache))
|
||||
self.assertEquals(0, StudentModule.objects.all().count())
|
||||
|
||||
self.kvs.set(student_state_key('a_field'), 'a_value')
|
||||
self.kvs.set(user_state_key('a_field'), 'a_value')
|
||||
|
||||
self.assertEquals(1, len(self.mdc.cache))
|
||||
self.assertEquals(1, StudentModule.objects.all().count())
|
||||
@@ -207,11 +207,11 @@ class TestMissingStudentModule(TestCase):
|
||||
|
||||
def test_delete_field_from_missing_student_module(self):
|
||||
"Test that deleting a field from a missing StudentModule raises a KeyError"
|
||||
self.assertRaises(KeyError, self.kvs.delete, student_state_key('a_field'))
|
||||
self.assertRaises(KeyError, self.kvs.delete, user_state_key('a_field'))
|
||||
|
||||
def test_has_field_for_missing_student_module(self):
|
||||
"Test that `has` returns False for missing StudentModules"
|
||||
self.assertFalse(self.kvs.has(student_state_key('a_field')))
|
||||
self.assertFalse(self.kvs.has(user_state_key('a_field')))
|
||||
|
||||
|
||||
class StorageTestBase(object):
|
||||
@@ -286,13 +286,13 @@ class TestContentStorage(StorageTestBase, TestCase):
|
||||
|
||||
class TestStudentPrefsStorage(StorageTestBase, TestCase):
|
||||
factory = StudentPrefsFactory
|
||||
scope = Scope.student_preferences
|
||||
key_factory = student_prefs_key
|
||||
scope = Scope.preferences
|
||||
key_factory = prefs_key
|
||||
storage_class = XModuleStudentPrefsField
|
||||
|
||||
|
||||
class TestStudentInfoStorage(StorageTestBase, TestCase):
|
||||
factory = StudentInfoFactory
|
||||
scope = Scope.student_info
|
||||
key_factory = student_info_key
|
||||
scope = Scope.user_info
|
||||
key_factory = user_info_key
|
||||
storage_class = XModuleStudentInfoField
|
||||
|
||||
@@ -1,26 +1,19 @@
|
||||
import logging
|
||||
from mock import MagicMock, patch
|
||||
from mock import MagicMock
|
||||
import datetime
|
||||
import factory
|
||||
import unittest
|
||||
import os
|
||||
|
||||
from django.test import TestCase
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.http import Http404
|
||||
from django.conf import settings
|
||||
from django.test.utils import override_settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from student.models import CourseEnrollment
|
||||
from xmodule.modulestore.django import modulestore, _MODULESTORES
|
||||
from xmodule.modulestore.exceptions import InvalidLocationError,\
|
||||
ItemNotFoundError, NoPathToItem
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
import courseware.views as views
|
||||
from xmodule.modulestore import Location
|
||||
|
||||
from .factories import UserFactory
|
||||
|
||||
|
||||
class Stub():
|
||||
pass
|
||||
@@ -55,7 +48,6 @@ class TestJumpTo(TestCase):
|
||||
def test_jumpto_invalid_location(self):
|
||||
location = Location('i4x', 'edX', 'toy', 'NoSuchPlace', None)
|
||||
jumpto_url = '%s/%s/jump_to/%s' % ('/courses', self.course_name, location)
|
||||
expected = 'courses/edX/toy/2012_Fall/courseware/Overview/'
|
||||
response = self.client.get(jumpto_url)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
@@ -124,3 +116,26 @@ class ViewsTestCase(TestCase):
|
||||
request, 'bar', ())
|
||||
self.assertRaisesRegexp(Http404, 'No data*', views.jump_to, request,
|
||||
'dummy', self.location)
|
||||
|
||||
def test_no_end_on_about_page(self):
|
||||
# Toy course has no course end date or about/end_date blob
|
||||
self.verify_end_date(self.course_id)
|
||||
|
||||
def test_no_end_about_blob(self):
|
||||
# test_end has a course end date, no end_date HTML blob
|
||||
self.verify_end_date("edX/test_end/2012_Fall", "Sep 17, 2015")
|
||||
|
||||
def test_about_blob_end_date(self):
|
||||
# test_about_blob_end_date has both a course end date and an end_date HTML blob.
|
||||
# HTML blob wins
|
||||
self.verify_end_date("edX/test_about_blob_end_date/2012_Fall", "Learning never ends")
|
||||
|
||||
def verify_end_date(self, course_id, expected_end_text=None):
|
||||
request = self.request_factory.get("foo")
|
||||
request.user = self.user
|
||||
result = views.course_about(request, course_id)
|
||||
if expected_end_text is not None:
|
||||
self.assertContains(result, "Classes End")
|
||||
self.assertContains(result, expected_end_text)
|
||||
else:
|
||||
self.assertNotContains(result, "Classes End")
|
||||
|
||||
@@ -630,6 +630,7 @@ def progress(request, course_id, student_id=None):
|
||||
'courseware_summary': courseware_summary,
|
||||
'grade_summary': grade_summary,
|
||||
'staff_access': staff_access,
|
||||
'student': student,
|
||||
}
|
||||
context.update()
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ Enrollments.
|
||||
"""
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from student.models import CourseEnrollment, assign_default_role
|
||||
from student.models import CourseEnrollment
|
||||
from django_comment_client.models import assign_default_role
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
||||
@@ -6,7 +6,8 @@ Enrollments.
|
||||
"""
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from student.models import CourseEnrollment, assign_default_role
|
||||
from student.models import CourseEnrollment
|
||||
from django_comment_client.models import assign_default_role
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
Reload forum (comment client) users from existing users.
|
||||
"""
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
import comment_client as cc
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Reload forum (comment client) users from existing users'
|
||||
|
||||
def adduser(self,user):
|
||||
print user
|
||||
try:
|
||||
cc_user = cc.User.from_django_user(user)
|
||||
cc_user.save()
|
||||
except Exception as err:
|
||||
print "update user info to discussion failed for user with id: %s" % user
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if len(args) != 0:
|
||||
uset = [User.objects.get(username=x) for x in args]
|
||||
else:
|
||||
uset = User.objects.all()
|
||||
|
||||
for user in uset:
|
||||
self.adduser(user)
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ from xmodule.modulestore import Location
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.exceptions import InvalidLocationError, ItemNotFoundError, NoPathToItem
|
||||
from xmodule.modulestore.search import path_to_location
|
||||
import xmodule.graders as xmgraders
|
||||
import track.views
|
||||
|
||||
from .offline_gradecalc import student_grades, offline_grades_available
|
||||
@@ -208,6 +209,10 @@ def instructor_dashboard(request, course_id):
|
||||
track.views.server_track(request, 'dump-answer-dist-csv', {}, page='idashboard')
|
||||
return return_csv('answer_dist_{0}.csv'.format(course_id), get_answers_distribution(request, course_id))
|
||||
|
||||
elif 'Dump description of graded assignments configuration' in action:
|
||||
track.views.server_track(request, action, {}, page='idashboard')
|
||||
msg += dump_grading_context(course)
|
||||
|
||||
elif "Reset student's attempts" in action or "Delete student state for problem" in action:
|
||||
# get the form data
|
||||
unique_student_identifier = request.POST.get('unique_student_identifier', '')
|
||||
@@ -1122,3 +1127,50 @@ def compute_course_stats(course):
|
||||
walk(course)
|
||||
stats = dict(counts) # number of each kind of module
|
||||
return stats
|
||||
|
||||
|
||||
def dump_grading_context(course):
|
||||
'''
|
||||
Dump information about course grading context (eg which problems are graded in what assignments)
|
||||
Very useful for debugging grading_policy.json and policy.json
|
||||
'''
|
||||
msg = "-----------------------------------------------------------------------------\n"
|
||||
msg += "Course grader:\n"
|
||||
|
||||
msg += '%s\n' % course.grader.__class__
|
||||
graders = {}
|
||||
if isinstance(course.grader, xmgraders.WeightedSubsectionsGrader):
|
||||
msg += '\n'
|
||||
msg += "Graded sections:\n"
|
||||
for subgrader, category, weight in course.grader.sections:
|
||||
msg += " subgrader=%s, type=%s, category=%s, weight=%s\n" % (subgrader.__class__, subgrader.type, category, weight)
|
||||
subgrader.index = 1
|
||||
graders[subgrader.type] = subgrader
|
||||
msg += "-----------------------------------------------------------------------------\n"
|
||||
msg += "Listing grading context for course %s\n" % course.id
|
||||
|
||||
gc = course.grading_context
|
||||
msg += "graded sections:\n"
|
||||
|
||||
msg += '%s\n' % gc['graded_sections'].keys()
|
||||
for (gs, gsvals) in gc['graded_sections'].items():
|
||||
msg += "--> Section %s:\n" % (gs)
|
||||
for sec in gsvals:
|
||||
s = sec['section_descriptor']
|
||||
format = getattr(s, 'format', None)
|
||||
aname = ''
|
||||
if format in graders:
|
||||
g = graders[format]
|
||||
aname = '%s %02d' % (g.short_label, g.index)
|
||||
g.index += 1
|
||||
elif s.display_name in graders:
|
||||
g = graders[s.display_name]
|
||||
aname = '%s' % g.short_label
|
||||
notes = ''
|
||||
if getattr(s, 'score_by_attempt', False):
|
||||
notes = ', score by attempt!'
|
||||
msg += " %s (format=%s, Assignment=%s%s)\n" % (s.display_name, format, aname, notes)
|
||||
msg += "all descriptors:\n"
|
||||
msg += "length=%d\n" % len(gc['all_descriptors'])
|
||||
msg = '<pre>%s</pre>' % msg.replace('<','<')
|
||||
return msg
|
||||
|
||||
@@ -39,12 +39,14 @@ def getip(request):
|
||||
|
||||
|
||||
def get_commit_id(course):
|
||||
return course.metadata.get('GIT_COMMIT_ID', 'No commit id')
|
||||
#return course.metadata.get('GIT_COMMIT_ID', 'No commit id')
|
||||
return getattr(course, 'GIT_COMMIT_ID', 'No commit id')
|
||||
# getattr(def_ms.courses[reload_dir], 'GIT_COMMIT_ID','No commit id')
|
||||
|
||||
|
||||
def set_commit_id(course, commit_id):
|
||||
course.metadata['GIT_COMMIT_ID'] = commit_id
|
||||
#course.metadata['GIT_COMMIT_ID'] = commit_id
|
||||
setattr(course, 'GIT_COMMIT_ID', commit_id)
|
||||
# setattr(def_ms.courses[reload_dir], 'GIT_COMMIT_ID', new_commit_id)
|
||||
|
||||
|
||||
@@ -124,7 +126,8 @@ def manage_modulestores(request, reload_dir=None, commit_id=None):
|
||||
|
||||
#----------------------------------------
|
||||
|
||||
dumpfields = ['definition', 'location', 'metadata']
|
||||
#dumpfields = ['definition', 'location', 'metadata']
|
||||
dumpfields = ['location', 'metadata']
|
||||
|
||||
for cdir, course in def_ms.courses.items():
|
||||
html += '<hr width="100%"/>'
|
||||
@@ -133,7 +136,7 @@ def manage_modulestores(request, reload_dir=None, commit_id=None):
|
||||
html += '<p>commit_id=%s</p>' % get_commit_id(course)
|
||||
|
||||
for field in dumpfields:
|
||||
data = getattr(course, field)
|
||||
data = getattr(course, field, None)
|
||||
html += '<h3>%s</h3>' % field
|
||||
if type(data) == dict:
|
||||
html += '<ul>'
|
||||
|
||||
@@ -15,7 +15,6 @@ from scipy.optimize import curve_fit
|
||||
from django.conf import settings
|
||||
from django.db.models import Sum, Max
|
||||
from psychometrics.models import *
|
||||
from xmodule.modulestore import Location
|
||||
|
||||
log = logging.getLogger("mitx.psychometrics")
|
||||
|
||||
@@ -246,13 +245,16 @@ def generate_plots_for_problem(problem):
|
||||
yset['ydat'] = ydat
|
||||
|
||||
if len(ydat) > 3: # try to fit to logistic function if enough data points
|
||||
cfp = curve_fit(func_2pl, xdat, ydat, [1.0, max_attempts / 2.0])
|
||||
yset['fitparam'] = cfp
|
||||
yset['fitpts'] = func_2pl(np.array(xdat), *cfp[0])
|
||||
yset['fiterr'] = [yd - yf for (yd, yf) in zip(ydat, yset['fitpts'])]
|
||||
fitx = np.linspace(xdat[0], xdat[-1], 100)
|
||||
yset['fitx'] = fitx
|
||||
yset['fity'] = func_2pl(np.array(fitx), *cfp[0])
|
||||
try:
|
||||
cfp = curve_fit(func_2pl, xdat, ydat, [1.0, max_attempts / 2.0])
|
||||
yset['fitparam'] = cfp
|
||||
yset['fitpts'] = func_2pl(np.array(xdat), *cfp[0])
|
||||
yset['fiterr'] = [yd - yf for (yd, yf) in zip(ydat, yset['fitpts'])]
|
||||
fitx = np.linspace(xdat[0], xdat[-1], 100)
|
||||
yset['fitx'] = fitx
|
||||
yset['fity'] = func_2pl(np.array(fitx), *cfp[0])
|
||||
except Exception as err:
|
||||
log.debug('Error in psychoanalyze curve fitting: %s' % err)
|
||||
|
||||
dataset['grade_%d' % grade] = yset
|
||||
|
||||
@@ -289,7 +291,7 @@ def generate_plots_for_problem(problem):
|
||||
'info': '',
|
||||
'data': jsdata,
|
||||
'cmd': '[%s], %s' % (','.join(jsplots), axisopts),
|
||||
})
|
||||
})
|
||||
|
||||
#log.debug('plots = %s' % plots)
|
||||
return msg, plots
|
||||
@@ -302,12 +304,12 @@ def make_psychometrics_data_update_handler(course_id, user, module_state_key):
|
||||
Construct and return a procedure which may be called to update
|
||||
the PsychometricsData instance for the given StudentModule instance.
|
||||
"""
|
||||
sm = studentmodule.objects.get_or_create(
|
||||
course_id=course_id,
|
||||
student=user,
|
||||
module_state_key=module_state_key,
|
||||
defaults={'state': '{}', 'module_type': 'problem'},
|
||||
)
|
||||
sm, status = StudentModule.objects.get_or_create(
|
||||
course_id=course_id,
|
||||
student=user,
|
||||
module_state_key=module_state_key,
|
||||
defaults={'state': '{}', 'module_type': 'problem'},
|
||||
)
|
||||
|
||||
try:
|
||||
pmd = PsychometricData.objects.using(db).get(studentmodule=sm)
|
||||
@@ -329,7 +331,11 @@ def make_psychometrics_data_update_handler(course_id, user, module_state_key):
|
||||
return
|
||||
|
||||
pmd.done = done
|
||||
pmd.attempts = state['attempts']
|
||||
try:
|
||||
pmd.attempts = state.get('attempts', 0)
|
||||
except:
|
||||
log.exception("no attempts for %s (state=%s)" % (sm, sm.state))
|
||||
|
||||
try:
|
||||
checktimes = eval(pmd.checktimes) # update log of attempt timestamps
|
||||
except:
|
||||
|
||||
BIN
lms/static/images/press/releases/stanford-university_102x57.png
Normal file
BIN
lms/static/images/press/releases/stanford-university_102x57.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
lms/static/images/press/releases/stanford-university_204x114.png
Normal file
BIN
lms/static/images/press/releases/stanford-university_204x114.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
BIN
lms/static/images/press/releases/stanford-university_240x135.png
Normal file
BIN
lms/static/images/press/releases/stanford-university_240x135.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 67 KiB |
@@ -144,10 +144,20 @@
|
||||
<li><div class="icon course-number"></div><p>Course Number</p><span class="course-number">${course.number}</span></li>
|
||||
<li><div class="icon start"></div><p>Classes Start</p><span class="start-date">${course.start_date_text}</span></li>
|
||||
|
||||
## End date should come from course.xml, but this is a quick hack
|
||||
% if get_course_about_section(course, "end_date"):
|
||||
<li><div class="icon end"></div><p>Classes End</p><span class="final-date">${get_course_about_section(course, "end_date")}</span></li>
|
||||
% endif
|
||||
## We plan to ditch end_date (which is not stored in course metadata),
|
||||
## but for backwards compatibility, show about/end_date blob if it exists.
|
||||
% if get_course_about_section(course, "end_date") or course.end:
|
||||
<li>
|
||||
<div class="icon end"></div>
|
||||
<p>Classes End</p><span class="final-date">
|
||||
% if get_course_about_section(course, "end_date"):
|
||||
${get_course_about_section(course, "end_date")}
|
||||
% else:
|
||||
${course.end_date_text}
|
||||
% endif
|
||||
</span>
|
||||
</li>
|
||||
% endif
|
||||
|
||||
% if get_course_about_section(course, "effort"):
|
||||
<li><div class="icon effort"></div><p>Estimated Effort</p><span class="start-date">${get_course_about_section(course, "effort")}</span></li>
|
||||
|
||||
@@ -156,6 +156,7 @@ function goto( mode)
|
||||
|
||||
<p>
|
||||
<input type="submit" name="action" value="Download CSV of answer distributions">
|
||||
<input type="submit" name="action" value="Dump description of graded assignments configuration">
|
||||
</p>
|
||||
<hr width="40%" style="align:left">
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ ${progress_graph.body(grade_summary, course.grade_cutoffs, "grade-detail-graph",
|
||||
|
||||
<section class="course-info">
|
||||
<header>
|
||||
<h1>Course Progress</h1>
|
||||
<h1>Course Progress for Student '${student.username}' (${student.email})</h1>
|
||||
</header>
|
||||
|
||||
%if not course.disable_progress_graph:
|
||||
|
||||
@@ -6,7 +6,16 @@
|
||||
<link type="text/html" rel="alternate" href="http://blog.edx.org/"/>
|
||||
<link type="application/atom+xml" rel="self" href="https://github.com/blog.atom"/>
|
||||
<title>EdX Blog</title>
|
||||
<updated>2013-03-15T14:00:12-07:00</updated>
|
||||
<updated>2013-04-03T14:00:12-07:00</updated>
|
||||
<entry>
|
||||
<id>tag:www.edx.org,2012:Post/17</id>
|
||||
<published>2012-12-19T14:00:00-07:00</published>
|
||||
<updated>2012-12-19T14:00:00-07:00</updated>
|
||||
<link type="text/html" rel="alternate" href="${reverse('press/stanford-to-work-with-edx')}"/>
|
||||
<title>Stanford University to Collaborate with edX on Development of Non-Profit Open Source edX Platform</title>
|
||||
<content type="html"><img src="${static.url('images/press/releases/stanford-university_204x114.png')}" />
|
||||
<p></p></content>
|
||||
</entry>
|
||||
<entry>
|
||||
<id>tag:www.edx.org,2013:Post/16</id>
|
||||
<published>2013-03-15T10:00:00-07:00</published>
|
||||
|
||||
@@ -159,13 +159,50 @@
|
||||
<li>Proactive, optimistic approach to problem solving.</li>
|
||||
<li>Commitment to constant personal and organizational improvement.</li>
|
||||
<li>Willingness to travel to partner sites as needed. </li>
|
||||
<li>Bachelors required, Master’s in Education, organizational learning, or other related field preferred. </li>
|
||||
<li>Bachelor's or Master’s in Education, organizational learning, or other related field preferred. But we're all about education, so let us know how you gained what you need to succeed in this role: projects after completing 6.00x or CS50x, Xbox cheevos, on-line guilds led, large scale innovations championed.</li>
|
||||
</ul>
|
||||
|
||||
<p>If you are interested in this position, please send an email to <a href="mailto:jobs@edx.org">jobs@edx.org</a>.</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
<article id="trainer" class="job">
|
||||
<div class="inner-wrapper">
|
||||
<h3><strong>TRAINER</strong></h3>
|
||||
<p>All those Universities on the edX homepage are full of incredible professors and teaching teams, designing on-line courses that will change the face of education. The edX team is constantly training whole new university teams on how to make their visions shine using edX software. We’re looking for some truly talented people to help train people on the tools that are enabling the future of education.</p>
|
||||
<p><strong>Responsibilities:</strong></p>
|
||||
<ul>
|
||||
<li>Facilitate training programs as required ensuring that best practices are incorporated in all learning environments.</li>
|
||||
<li>Create and design learning materials for training curriculums, incorporate edX best practices into training curriculum.</li>
|
||||
<li>Incorporate key performance metrics into training modules; participate in strategic initiatives</li>
|
||||
<li>Measure, monitor and share training results with business units to identify future training opportunities.</li>
|
||||
<li>Identify and leverage existing resources to maximize partner efficiency and productivity. </li>
|
||||
<li>Work with both Universities and edX to provide strategic input based on future training needs.</li>
|
||||
<li>Communicate effectively in oral and written presentations.</li>
|
||||
<li>Analyze learners training needs and identify cross training opportunities.</li>
|
||||
<li>Mentor and train others on training tools to expand training efficiency and uniformity.</li>
|
||||
<li>Build relationships with universities to be viewed as a trusted training partner. </li>
|
||||
</ul>
|
||||
<p><strong>Requirements:</strong></p>
|
||||
<ul>
|
||||
<li>Minimum of 1-3 years experience developing and delivering educational training, preferably in an educational technology organization. </li>
|
||||
<li>Lean and Agile thinking and training. Experienced in Scrum or kanban preferred.</li>
|
||||
<li>Excellent interpersonal skills including proven presentation and facilitation skills.</li>
|
||||
<li>Strong oral and written communication skills.</li>
|
||||
<li>Flexibility to work on a variety of initiatives; prior startup experience preferred.</li>
|
||||
<li>Outstanding work ethic, results-oriented, and creative/innovative style.</li>
|
||||
<li>Proactive, optimistic approach to problem solving.</li>
|
||||
<li>Commitment to constant personal and organizational improvement.</li>
|
||||
<li>Willingness to travel to partner sites as needed.</li>
|
||||
<li>Bachelors or Master’s in Education, organizational learning, instructional design or other related field preferred. But we're all about education, so let us know how you gained what you need to succeed in this role: projects after completing 6.00x or CS50x, Xbox cheevos, on-line guilds led, large scale innovations championed.</li>
|
||||
</ul>
|
||||
|
||||
<p>If you are interested in this position, please send an email to <a href="mailto:jobs@edx.org">jobs@edx.org</a>.</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
<article id="instructional-designer" class="job">
|
||||
<div class="inner-wrapper">
|
||||
<h3><strong>INSTRUCTIONAL DESIGNER</strong></h3>
|
||||
@@ -187,8 +224,10 @@
|
||||
</ul>
|
||||
<p><strong>Qualifications:</strong></p>
|
||||
<ul>
|
||||
<li>Master's Degree in Educational Technology, Instructional Design or related field. Experience in higher education with additional experience in a start-up or research environment preferable.</li>
|
||||
<li>Excellent interpersonal and communication (written and verbal), project management, problem-solving and time management skills. The ability to be flexible with projects and to work on multiple courses essential.</li> Ability to meet deadlines and manage expectations of constituents.
|
||||
<li>Master's Degree in Educational Technology, Instructional Design or related field. Experience in higher education with additional experience in a start-up or research environment preferable. But we're all about education, so let us know how you gained what you need to succeed in this role: projects after completing 6.00x or CS50x, Xbox cheevos, on-line guilds led, large scale innovations championed.</li>
|
||||
<li>Experience in higher education with additional experience in a start-up or research environment preferable.</li>
|
||||
<li>Excellent interpersonal and communication (written and verbal), project management, problem-solving and time management skills. The ability to be flexible with projects and to work on multiple courses essential.</li>
|
||||
<li>Ability to meet deadlines and manage expectations of constituents.</li>
|
||||
<li>Capacity to develop new and relevant technology skills. Experience using game theory design and learning analytics to inform instructional design decisions and strategy.</li>
|
||||
<li>Technical Skills: Video and screencasting experience. LMS Platform experience, xml, HTML, CSS, Adobe Design Suite, Camtasia or Captivate experience. Experience with web 2.0 collaboration tools.</li>
|
||||
</ul>
|
||||
@@ -205,16 +244,16 @@
|
||||
<p>edX Program Managers (PM) lead the edX's course production process. They are systems thinkers who manage the creation of a course from start to finish. PMs work with University Professors and course staff to help them take advantage of edX services to create world class online learning offerings and encourage the exploration of an emerging form of higher education.</p>
|
||||
<p><strong>Responsibilities:</strong></p>
|
||||
<ul>
|
||||
<li>Create and execute the course production cycle. PMs are able to examine and explain what they do in great detail and able to think abstractly about people, time, and processes. They coordinate the efforts of multiple</li> teams engaged in the production of the courses assigned to them.
|
||||
<li>Create and execute the course production cycle. PMs are able to examine and explain what they do in great detail and able to think abstractly about people, time, and processes. They coordinate the efforts of multiple teams engaged in the production of the courses assigned to them.</li>
|
||||
<li>Train partners and drive best practices adoption. PMs train course staff from partner institutions and help them adopt best practices for workflow and tools. </li>
|
||||
<li>Build capacity. Mentor staff at partner institutions, train the trainers that help them scale their course production ability.</li>
|
||||
<li>Create visibility. PMs are responsible for making the state of the course production system accessible and comprehensible to all stakeholders. They are capable of training Course development teams in Scrum and</li> Kanban, and are Lean thinkers and educators.
|
||||
<li>Create visibility. PMs are responsible for making the state of the course production system accessible and comprehensible to all stakeholders. They are capable of training Course development teams in Scrum and Kanban, and are Lean thinkers and educators.</li>
|
||||
<li>Improve workflows. PMs are responsible for carefully assessing the methods and outputs of each course and adjusting them to take best advantage of available resources.</li>
|
||||
<li>Encourage innovation. Spark creativity in course teams to build new courses that could never be produced in brick and mortar settings.</li>
|
||||
</ul>
|
||||
<p><strong>Qualifications:</strong></p>
|
||||
<ul>
|
||||
<li>Bachelor's Degree. Master's Degree preferred.</li>
|
||||
<li>Bachelor's Degree. Master's Degree preferred. But we're all about education, so let us know how you gained what you need to succeed in this role: projects after completing 6.00x or CS50x, Xbox cheevos, on-line guilds led, large scale innovations championed.</li>
|
||||
<li>At least 2 years of experience working with University faculty and administrators.</li>
|
||||
<li>Proven record of successful Scrum or Kanban project management, including use of project management tools. </li>
|
||||
<li>Ability to create processes that systematically provide solutions to open ended challenges.</li>
|
||||
@@ -237,36 +276,6 @@
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article id="project-manager-pmo" class="job">
|
||||
<div class="inner-wrapper">
|
||||
<h3><strong>PROJECT MANAGER (PMO)</strong></h3>
|
||||
<p>As a fast paced, rapidly growing organization serving the evolving online higher education market, edX maximizes its talents and resources. To help make the most of this unapologetically intelligent and dedicated team, we seek a project manager to increase the accuracy of our resource and schedule estimates and our stakeholder satisfaction.</p>
|
||||
<p><strong>Responsibilities:</strong></p>
|
||||
<ul>
|
||||
<li>Coordinate multiple projects to bring Courses, Software Product and Marketing initiatives to market, all of which are related, which have both dedicated and shared resources.</li>
|
||||
<li>Provide, at a moment’s notice, the state of development, so that priorities can be enforced or reset, so that future expectations can be set accurately.</li>
|
||||
<li>Develop lean processes that supports a wide variety of efforts which draw on a shared resource pool.</li>
|
||||
<li>Develop metrics on resource use that support the leadership team in optimizing how they respond to unexpected challenges and new opportunities.</li>
|
||||
<li>Accurately and clearly escalate only those issues which need escalation for productive resolution. Assist in establishing consensus for all other issues.</li>
|
||||
<li>Advise the team on best practices, whether developed internally or as industry standards.</li>
|
||||
<li>Recommend to the leadership team how to re-deploy key resources to better match stated priorities.</li>
|
||||
<li>Help the organization deliver on its commitments with more consistency and efficiency. Allow the organization to respond to new opportunities with more certainty in its ability to forecast resource needs.</li>
|
||||
<li>Select and maintain project management tools for Scrum and Kanban that can serve as the standard for those we use with our partners.</li>
|
||||
<li>Forecast future resource needs given the strategic direction of the organization.</li>
|
||||
</ul>
|
||||
<p><strong>Skills:</strong></p>
|
||||
<ul>
|
||||
<li>Bachelor’s degree or higher</li>
|
||||
<li>Exquisite communication skills, especially listening</li>
|
||||
<li>Inexhaustible attention to detail with the ability to let go of perfection</li>
|
||||
<li>Deep commitment to Lean project management, including a dedication to its best intentions not just its rituals</li>
|
||||
<li>Sense of humor and humility</li>
|
||||
<li>Ability to hold on to the important in the face of the urgent</li>
|
||||
</ul>
|
||||
<p>If you are interested in this position, please send an email to <a href="mailto:jobs@edx.org">jobs@edx.org</a>.</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
<article id="director-of-product-management" class="job">
|
||||
<div class="inner-wrapper">
|
||||
@@ -286,8 +295,7 @@
|
||||
</ul>
|
||||
<p><strong>Qualifications:</strong></p>
|
||||
<ul>
|
||||
<li>Bachelor’s degree or higher in a Technical Area</li>
|
||||
<li>MBA or Masters in Design preferred</li>
|
||||
<li>Bachelor’s degree or higher in a Technical Area, MBA or Masters in Design preferred. But we're all about education, so let us know how you gained what you need to succeed in this role: projects after completing 6.00x or CS50x, Xbox cheevos, on-line guilds led, large scale innovations championed.</li>
|
||||
<li>Proven ability to develop and implement strategy</li>
|
||||
<li>Exquisite organizational skills</li>
|
||||
<li>Deep analytical skills</li>
|
||||
@@ -319,7 +327,7 @@
|
||||
</ul>
|
||||
<p><strong>Qualifications:</strong></p>
|
||||
<ul>
|
||||
<li>Bachelor’s degree or higher</li>
|
||||
<li>Bachelor’s degree or higher. But we're all about education, so let us know how you gained what you need to succeed in this role: projects after completing 6.00x or CS50x, Xbox cheevos, on-line guilds led, large scale innovations championed.</li>
|
||||
<li>Thorough knowledge of Python, DJango, XML,HTML, CSS , Javascript and backbone.js</li>
|
||||
<li>Ability to work on multiple projects simultaneously without splintering</li>
|
||||
<li>Tactfully escalate conflicting deadlines or priorities only when needed. Otherwise help the team members negotiate a solution.</li>
|
||||
@@ -358,7 +366,7 @@
|
||||
<li>Test Driven Development</li>
|
||||
<li>Committed to Documentation best practices so your code can be consumed in an open source environment</li>
|
||||
<li>Contributor to or consumer of Open Source Frameworks</li>
|
||||
<li>BS in Computer Science from top-tier institution</li>
|
||||
<li>BS in Computer Science from top-tier institution. But we're all about education, so let us know how you gained what you need to succeed in this role: projects after completing 6.00x or CS50x, Xbox cheevos, on-line guilds led, large scale innovations championed.</li>
|
||||
<li>Acknowledged by peers as a technology leader </li>
|
||||
</ul>
|
||||
|
||||
@@ -367,6 +375,51 @@
|
||||
</article>
|
||||
|
||||
|
||||
<article id="devops-engineer-systems-administrator" class="job">
|
||||
<div class="inner-wrapper">
|
||||
<h3><strong>DEVOPS ENGINEER – SYESTEMS ADMINISTRATOR</strong></h3>
|
||||
<p>The Devop Engineers at edX help develop and maintain the infrastructure in AWS for all services and systems required to run edX. We're seeking a capable systems administrator who is unafraid of scripting languages and development to build out tools in order to improve the functionality of edX. The devops team primarily focuses on the provisioning, configuration, and deployment of services at edX. If you have a passion for automation and constant improvement then we want to hear from you. Our production environment is primarily built on Ubuntu (in AWS) and we use Puppet and Fabric to manage most of the environment.</p>
|
||||
<p>In addition to the primary task of building infrastructure the Devops team supports the developers in a variety of other contexts, including helping with desktop development environments if required. We participate in on-call and emergency support and there will be occasional out of normal hours work required.</p>
|
||||
<p><strong>Responsibilities:</strong></p>
|
||||
<ul>
|
||||
<li>Work with developers and staff to maintain and improve the infrastructure of edX.</li>
|
||||
<li>Assist where needed with other technical support tasks to support the fast moving pace of edX.</li>
|
||||
<li>Rapidly diagnose and resolve faults with organization-wide servers and services, and communicate to users as appropriate.</li>
|
||||
</ul>
|
||||
<p><strong>Requirements:</strong></p>
|
||||
<ul>
|
||||
<li>Bachelor's degree in engineering or computer science. But we're all about education, so let us know how you gained what you need to succeed in this role: projects after completing 6.00x or CS50x, Xbox cheevos, on-line guilds led, large scale innovations championed.3 or more years of systems administration. </li>
|
||||
<li>Must have an excellent working knowledge of Linux both as an end-user and as an administrator.</li>
|
||||
<li>Must be adept in programming/scripting languages such as Python, Ruby, Bash.</li>
|
||||
<li>Must be familiar with a configuration management system such as Puppet, Chef, Ansible.</li>
|
||||
<li>Must have experience running web applications in a production environment.</li>
|
||||
<li>Must have excellent personal interaction skills as the position requires interfacing with a wide range of people up to board level.</li>
|
||||
<li>Ideally possesses experience with some of the following technologies: nginx, mysql, mongodb, django environments, splunk, git.</li>
|
||||
</ul>
|
||||
|
||||
<p>If you are interested in this position, please send an email to <a href="mailto:jobs@edx.org">jobs@edx.org</a>.</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
<article id="learning-sciences-engineer" class="job">
|
||||
<div class="inner-wrapper">
|
||||
<h3><strong>LEARNING SCIENCES ENGINEER</strong></h3>
|
||||
<p>In 2012, edX reinvented education. In 2013, the edX learning sciences team is charged with reinventing education, again. The goal of the team is to prototype and develop technologies which will radically change the way students learn and instructors teach. We will engage in projects in learning analytics, crowdsourced content development, intelligent tutoring, as well as radical changes to the ways course content is structured. We are looking to opportunistically build a small (3 person), fast-moving team capable of rapidly bringing advanced development projects to prototype and to market. All members of the team must be spectacular software engineers capable of working in or adapting to dynamic, duck typed, functional languages (Python and JavaScript). In addition, we are looking for some combination of:</p>
|
||||
<ul>
|
||||
<li>Deep expertise in mathematics, and in particular, advanced linear algebra, machine learning, big data, psychometrics, and probability. </li>
|
||||
<li>UX design. Capable of envisioning user interface for software that does things that have never been done before, and bringing them through to market. Skills should be broad and range the full gamut: graphic design, UX, HTML5, basic JavaScript, and CSS. </li>
|
||||
<li>Interest and experience in both research and practice of education, cognitive science, and related fields. </li>
|
||||
<li>Core backend experience (Python, Django, MongoDB, SQL)</li>
|
||||
<li>Background in social networks and social network analysis (both social science and mathematics) is desirable as well.</li>
|
||||
</ul>
|
||||
<p>More than anything, we’re looking for spectacular people capable of very rapidly building things which have never been built before. We’re capable of providing both traditional employment, and potentially, in partnership with MIT, more academic opportunities.</p>
|
||||
|
||||
<p>If you are interested in this position, please send an email to <a href="mailto:jobs@edx.org">jobs@edx.org</a>.</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
<section class="jobs-sidebar">
|
||||
@@ -374,12 +427,14 @@
|
||||
<nav>
|
||||
<a href="#director-of-education-services">Director of Education Services</a>
|
||||
<a href="#manager-of-training-services">Manager of Training Services</a>
|
||||
<a href="#trainer">Trainer</a>
|
||||
<a href="#instructional-designer">Instructional Designer</a>
|
||||
<a href="#program-manager">Program Manager</a>
|
||||
<a href="#project-manager-pmo">Project Manager (PMO)</a>
|
||||
<a href="#director-of-product-management">Director of Product Management</a>
|
||||
<a href="#content-engineer">Content Engineer</a>
|
||||
<a href="#software-engineer">Software Engineer</a>
|
||||
<a href="#devops-engineer-systems-administrator">Devops Engineer - Systems Administrator</a>
|
||||
<a href="#learning-sciences-engineer">Learning Sciences Engineer</a>
|
||||
</nav>
|
||||
<h2>How to Apply</h2>
|
||||
<p>E-mail your resume, cover letter and any other materials to <a href="mailto:jobs@edx.org">jobs@edx.org</a></p>
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<%! from django.core.urlresolvers import reverse %>
|
||||
<%inherit file="../../main.html" />
|
||||
|
||||
<%namespace name='static' file='../../static_content.html'/>
|
||||
|
||||
<%block name="title"><title>Stanford University to Collaborate with edX on Development of Non-Profit Open Source edX Platform</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>Stanford University to Collaborate with edX on Development of Non-Profit Open Source edX Platform</h1>
|
||||
<hr class="horizontal-divider">
|
||||
<article>
|
||||
<h2>edX Learning Platform to be open source and available on June 1</h2>
|
||||
|
||||
<p><strong>CAMBRIDGE, MA and STANFORD, CA – April 3, 2013 –</strong>
|
||||
|
||||
Stanford University and <a href="https://www.edx.org">edX</a>, the not-for-profit online learning enterprise founded by Harvard University and the Massachusetts Institute of Technology (MIT), today announced their collaboration to advance the development of edX’s open source learning platform and provide free and open online learning tools for institutions around the world.</p>
|
||||
|
||||
<p>As part of this announcement, edX will release the source code for its entire online learning platform on June 1, 2013. In support of that move, Stanford will integrate features of its existing Class2Go platform into the edX platform, use the integration as an internal platform for online coursework for on-campus and distance learners, and work collaboratively with edX and other institutions to further develop the edX platform.</p>
|
||||
|
||||
<p>“This collaboration brings together two leaders in online education in a common effort to ensure that the world’s universities have the strongest possible not-for-profit, open source platform available to them,” said John Mitchell, vice provost for online learning at Stanford University. “A not-for-profit, open source platform will help universities experiment with different ways to produce and share content, fostering continued innovation through a vibrant community of contributors.”</p>
|
||||
|
||||
<p>EdX and Stanford will collaborate along with others around the globe on the ongoing development and refinement of the edX online learning platform. As of June 1, developers everywhere will be able to freely access the source code of the edX learning platform, including code for its Learning Management System (LMS); Studio, a course authoring tool; xBlock, an application programming interface (API) for integrating third-party learning objects; and machine grading API’s. EdX will support and nurture the community of developers contributing to the enhancement of the edX platform by providing a rich environment for developer collaboration as well as technical and process guidelines to facilitate developer contributions.</p>
|
||||
|
||||
<p>“It has been our vision to offer our platform as open source since edX’s founding by Harvard and MIT,” stated Anant Agarwal, president of edX. “We are now realizing that vision, and I am pleased to welcome Stanford University, one of the world’s leading institutions of higher education, to further this global open source solution. I want to acknowledge the key role played by our X Consortium member UC Berkeley, which was instrumental in fostering this collaboration. We believe the edX platform—the Linux of learning—will benefit from all the world’s institutions and communities.”</p>
|
||||
|
||||
<p>EdX is pursuing an open source vision to enhance access to higher education for the entire world. One of the chief benefits of massive open online courses (MOOCs) is that they bring together a tremendously diverse student body to learn with and from each other. EdX has chosen to extend that perspective to its learning platform as well, knowing that drawing upon the global community of developers is an effective route to both transform and deliver the world’s best and most accessible online and blended learning experience.</p>
|
||||
|
||||
<p>MOOCs and innovative online teaching approaches on college campuses, such as the “flipped classroom,” use web environments that support interactive video, online discussion, social/cohort interaction, assessment and other functions. Open source online learning platforms will allow universities to develop their own delivery methods, partner with other universities and institutions as they choose, collect data, and control branding of their educational material. Further developing online opportunities through open source technology is a key objective of the partnership between edX and Stanford.</p>
|
||||
|
||||
<p>Stanford will continue to provide a range of platforms for its instructors to choose from in hosting their online coursework, including continued partnerships with Coursera and other providers. The university will focus its ongoing platform development efforts on the new platform, combining key features from the Class2Go open source platform with the open source edX code base.</p>
|
||||
|
||||
<p>The edX learning platform source code, as well as platform developments from Stanford, edX and other contributors, will be available on June 1, 2013 and can be accessed from the edX Platform Repository located at <a href="https://github.com/edX">https://github.com/edX</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>
|
||||
|
||||
<h2>About Stanford University</h2>
|
||||
|
||||
<p>
|
||||
<a href="http://www.stanford.edu">Stanford University</a> is engaged in a variety of efforts to develop online learning – experimenting with coursework for both on-campus and off-campus students, researching key questions around what a digital environment means for teaching and learning, and pursuing platform development. More information on Stanford’s online learning activities is available at <a href="http://online.stanford.edu">http://online.stanford.edu</a>
|
||||
|
||||
|
||||
<section class="contact">
|
||||
<p><strong>Media Contact:</strong></p>
|
||||
<p>Dan O'Connell</p>
|
||||
<p>oconnell@edx.org</p>
|
||||
<p>(617) 480-6585</p>
|
||||
</section>
|
||||
|
||||
<section class="contact">
|
||||
<p>Brad Hayward</p>
|
||||
<p>bhayward@stanford.edu</p>
|
||||
<p>650-724-0199</p>
|
||||
</section>
|
||||
|
||||
<section class="contact">
|
||||
<p>Lisa Lapin</p>
|
||||
<p>lapin@stanford.edu</p>
|
||||
<p>650-725-8396</p>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="footer">
|
||||
<hr class="horizontal-divider">
|
||||
<div class="logo"></div><h3 class="date">DATE: 04 - 03 - 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=:Stanford+to+work+with+edX+http://www.edx.org/press/stanford-to-work-with-edx" class="share">
|
||||
<img src="${static.url('images/social/twitter-sharing.png')}">
|
||||
</a>
|
||||
</a>
|
||||
<a href="mailto:?subject=Stanford%20to%20work%20with%20EdX…http://edx.org/press/stanford-to-work-with-edx" class="share">
|
||||
<img src="${static.url('images/social/email-sharing.png')}">
|
||||
</a>
|
||||
<div class="fb-like" data-href="http://edx.org/press/stanford-to-work-with-edx" data-send="true" data-width="450" data-show-faces="true"></div>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
</section>
|
||||
</section>
|
||||
@@ -17,7 +17,7 @@
|
||||
</%block>
|
||||
|
||||
<%block name="university_description">
|
||||
<p>The University of Texas at Austin is the top-ranked public university in a nearly 1,000-mile radius, and is ranked in the top 25 universities in the world. Students have been finding their passion in life at UT Austin for more than 130 years, and it has been a member of the prestigious AAU since 1929. UT Austin combines the academic depth and breadth of a world research institute (regularly ranking within the top three producers of doctoral degrees in the country) with the fun and excitement of a big-time collegiate experience. It is currently the fifth-largest university in America, with more than 50,000 students and 3,000 professors across 17 colleges and schools, and is the first major American university to build a medical school in the past 50 years.</p>
|
||||
<p>The University of Texas at Austin is the top-ranked public university in a nearly 1,000-mile radius, and is ranked in the top 25 universities in the world. Students have been finding their passion in life at UT Austin for more than 130 years, and it has been a member of the prestigious AAU since 1929. UT Austin combines the academic depth and breadth of a world research institute (regularly ranking within the top three producers of doctoral degrees in the country) with the fun and excitement of a big-time collegiate experience. It is currently the fifth-largest university in America, with more than 50,000 students and 3,000 professors across 17 colleges and schools. UT Austin will be opening the Dell Medical School in 2016.</p>
|
||||
</%block>
|
||||
|
||||
${parent.body()}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<%block name="university_description">
|
||||
<p>Educating students, providing care for patients, conducting groundbreaking research and serving the needs of Texans and the nation for more than 130 years, The University of Texas System is one of the largest public university systems in the United States, with nine academic universities and six health science centers. Student enrollment exceeded 215,000 in the 2011 academic year. The UT System confers more than one-third of the state’s undergraduate degrees and educates nearly three-fourths of the state’s health care professionals annually. The UT System has an annual operating budget of $13.1 billion (FY 2012) including $2.3 billion in sponsored programs funded by federal, state, local and private sources. With roughly 87,000 employees, the UT System is one of the largest employers in the state.</p>
|
||||
<p>Find out about the <a href="${reverse('university_profile', args=['UTAustinX'])}">University of Texas Austin</a>.</p>
|
||||
<p>Find out about <a href="${reverse('university_profile', args=['UTAustinX'])}">The University of Texas at Austin</a>.</p>
|
||||
</%block>
|
||||
|
||||
${parent.body()}
|
||||
|
||||
@@ -153,6 +153,9 @@ urlpatterns = ('',
|
||||
url(r'^press/xblock_announcement$', 'static_template_view.views.render',
|
||||
{'template': 'press_releases/xblock_announcement.html'},
|
||||
name="press/xblock-announcement"),
|
||||
url(r'^press/stanford-to-work-with-edx$', 'static_template_view.views.render',
|
||||
{'template': 'press_releases/stanford_announcement.html'},
|
||||
name="press/stanford-to-work-with-edx"),
|
||||
|
||||
# Should this always update to point to the latest press release?
|
||||
(r'^pressrelease$', 'django.views.generic.simple.redirect_to',
|
||||
|
||||
Reference in New Issue
Block a user