Commit 87ff18dc by Chris Dodge

Merge branch 'feature/cale/cms-master' of github.com:MITx/mitx into…

Merge branch 'feature/cale/cms-master' of github.com:MITx/mitx into feature/cdodge/import-course-info
parents 55c69a1e 9d92711d
...@@ -7,3 +7,4 @@ python ...@@ -7,3 +7,4 @@ python
yuicompressor yuicompressor
node node
graphviz graphviz
mysql
...@@ -3,8 +3,7 @@ from staticfiles.storage import staticfiles_storage ...@@ -3,8 +3,7 @@ from staticfiles.storage import staticfiles_storage
from pipeline_mako import compressed_css, compressed_js from pipeline_mako import compressed_css, compressed_js
%> %>
<%def name='url(file)'> <%def name='url(file)'><%
<%
try: try:
url = staticfiles_storage.url(file) url = staticfiles_storage.url(file)
except: except:
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<div style="display:none;" name="${hidden}" inputid="input_${id}" /> <div style="display:none;" name="${hidden}" inputid="input_${id}" />
% endif % endif
<input type="text" name="input_${id}" id="input_${id}" value="${value}" <input type="text" name="input_${id}" id="input_${id}" value="${value|h}"
% if size: % if size:
size="${size}" size="${size}"
% endif % endif
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
% endif % endif
<p class="debug">${status}</p> <p class="debug">${status}</p>
<input type="file" name="input_${id}" id="input_${id}" value="${value}" multiple="multiple" data-required_files="${required_files}" data-allowed_files="${allowed_files}"/> <input type="file" name="input_${id}" id="input_${id}" value="${value}" multiple="multiple" data-required_files="${required_files|h}" data-allowed_files="${allowed_files|h}"/>
</div> </div>
<div class="message">${msg|n}</div> <div class="message">${msg|n}</div>
</section> </section>
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<input type="hidden" name="input_${id}" id="input_${id}" class="javascriptinput_input"/> <input type="hidden" name="input_${id}" id="input_${id}" class="javascriptinput_input"/>
<div class="javascriptinput_data" data-display_class="${display_class}" <div class="javascriptinput_data" data-display_class="${display_class}"
data-problem_state="${problem_state}" data-params="${params}" data-problem_state="${problem_state}" data-params="${params}"
data-submission="${value}" data-evaluation="${evaluation}"> data-submission="${value|h}" data-evaluation="${msg|h}">
</div> </div>
<div class="script_placeholder" data-src="/static/js/${display_file}"></div> <div class="script_placeholder" data-src="/static/js/${display_file}"></div>
<div class="javascriptinput_container"></div> <div class="javascriptinput_container"></div>
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<div style="display:none;" name="${hidden}" inputid="input_${id}" /> <div style="display:none;" name="${hidden}" inputid="input_${id}" />
% endif % endif
<input type="text" name="input_${id}" id="input_${id}" value="${value}" <input type="text" name="input_${id}" id="input_${id}" value="${value|h}"
% if do_math: % if do_math:
class="math" class="math"
% endif % endif
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<div class="incorrect" id="status_${id}"> <div class="incorrect" id="status_${id}">
% endif % endif
<input type="text" name="input_${id}" id="input_${id}" value="${value}" <input type="text" name="input_${id}" id="input_${id}" value="${value|h}"
style="display:none;" style="display:none;"
/> />
......
...@@ -2,9 +2,18 @@ ...@@ -2,9 +2,18 @@
Tests of input types. Tests of input types.
TODO: TODO:
- refactor: so much repetive code (have factory methods that build xml elements directly, etc)
- test error cases
- check rendering -- e.g. msg should appear in the rendered output. If possible, test that
templates are escaping things properly.
- test unicode in values, parameters, etc. - test unicode in values, parameters, etc.
- test various html escapes - test various html escapes
- test funny xml chars -- should never get xml parse error if things are escaped properly. - test funny xml chars -- should never get xml parse error if things are escaped properly.
""" """
from lxml import etree from lxml import etree
...@@ -46,6 +55,19 @@ class OptionInputTest(unittest.TestCase): ...@@ -46,6 +55,19 @@ class OptionInputTest(unittest.TestCase):
self.assertEqual(context, expected) self.assertEqual(context, expected)
def test_option_parsing(self):
f = inputtypes.OptionInput.parse_options
def check(input, options):
"""Take list of options, confirm that output is in the silly doubled format"""
expected = [(o, o) for o in options]
self.assertEqual(f(input), expected)
check("('a','b')", ['a', 'b'])
check("('a', 'b')", ['a', 'b'])
check("('a b','b')", ['a b', 'b'])
check("('My \"quoted\"place','b')", ['My \"quoted\"place', 'b'])
class ChoiceGroupTest(unittest.TestCase): class ChoiceGroupTest(unittest.TestCase):
''' '''
Test choice groups, radio groups, and checkbox groups Test choice groups, radio groups, and checkbox groups
...@@ -73,6 +95,7 @@ class ChoiceGroupTest(unittest.TestCase): ...@@ -73,6 +95,7 @@ class ChoiceGroupTest(unittest.TestCase):
expected = {'id': 'sky_input', expected = {'id': 'sky_input',
'value': 'foil3', 'value': 'foil3',
'status': 'answered', 'status': 'answered',
'msg': '',
'input_type': expected_input_type, 'input_type': expected_input_type,
'choices': [('foil1', '<text>This is foil One.</text>'), 'choices': [('foil1', '<text>This is foil One.</text>'),
('foil2', '<text>This is foil Two.</text>'), ('foil2', '<text>This is foil Two.</text>'),
...@@ -119,12 +142,13 @@ class JavascriptInputTest(unittest.TestCase): ...@@ -119,12 +142,13 @@ class JavascriptInputTest(unittest.TestCase):
context = the_input._get_render_context() context = the_input._get_render_context()
expected = {'id': 'prob_1_2', expected = {'id': 'prob_1_2',
'status': 'unanswered',
'msg': '',
'value': '3',
'params': params, 'params': params,
'display_file': display_file, 'display_file': display_file,
'display_class': display_class, 'display_class': display_class,
'problem_state': problem_state, 'problem_state': problem_state,}
'value': '3',
'evaluation': '',}
self.assertEqual(context, expected) self.assertEqual(context, expected)
...@@ -204,9 +228,6 @@ class FileSubmissionTest(unittest.TestCase): ...@@ -204,9 +228,6 @@ class FileSubmissionTest(unittest.TestCase):
element = etree.fromstring(xml_str) element = etree.fromstring(xml_str)
escapedict = {'"': '&quot;'}
esc = lambda s: saxutils.escape(s, escapedict)
state = {'value': 'BumbleBee.py', state = {'value': 'BumbleBee.py',
'status': 'incomplete', 'status': 'incomplete',
'feedback' : {'message': '3'}, } 'feedback' : {'message': '3'}, }
...@@ -220,8 +241,8 @@ class FileSubmissionTest(unittest.TestCase): ...@@ -220,8 +241,8 @@ class FileSubmissionTest(unittest.TestCase):
'msg': input_class.submitted_msg, 'msg': input_class.submitted_msg,
'value': 'BumbleBee.py', 'value': 'BumbleBee.py',
'queue_len': '3', 'queue_len': '3',
'allowed_files': esc('["runme.py", "nooooo.rb", "ohai.java"]'), 'allowed_files': '["runme.py", "nooooo.rb", "ohai.java"]',
'required_files': esc('["cookies.py"]')} 'required_files': '["cookies.py"]'}
self.assertEqual(context, expected) self.assertEqual(context, expected)
...@@ -255,14 +276,15 @@ class CodeInputTest(unittest.TestCase): ...@@ -255,14 +276,15 @@ class CodeInputTest(unittest.TestCase):
'status': 'incomplete', 'status': 'incomplete',
'feedback' : {'message': '3'}, } 'feedback' : {'message': '3'}, }
the_input = lookup_tag('codeinput')(test_system, element, state) input_class = lookup_tag('codeinput')
the_input = input_class(test_system, element, state)
context = the_input._get_render_context() context = the_input._get_render_context()
expected = {'id': 'prob_1_2', expected = {'id': 'prob_1_2',
'value': 'print "good evening"', 'value': 'print "good evening"',
'status': 'queued', 'status': 'queued',
'msg': 'Submitted to grader.', 'msg': input_class.submitted_msg,
'mode': mode, 'mode': mode,
'linenumbers': linenumbers, 'linenumbers': linenumbers,
'rows': rows, 'rows': rows,
...@@ -311,8 +333,9 @@ class SchematicTest(unittest.TestCase): ...@@ -311,8 +333,9 @@ class SchematicTest(unittest.TestCase):
expected = {'id': 'prob_1_2', expected = {'id': 'prob_1_2',
'value': value, 'value': value,
'initial_value': initial_value,
'status': 'unsubmitted', 'status': 'unsubmitted',
'msg': '',
'initial_value': initial_value,
'width': width, 'width': width,
'height': height, 'height': height,
'parts': parts, 'parts': parts,
...@@ -476,6 +499,7 @@ class ChemicalEquationTest(unittest.TestCase): ...@@ -476,6 +499,7 @@ class ChemicalEquationTest(unittest.TestCase):
expected = {'id': 'prob_1_2', expected = {'id': 'prob_1_2',
'value': 'H2OYeah', 'value': 'H2OYeah',
'status': 'unanswered', 'status': 'unanswered',
'msg': '',
'size': size, 'size': size,
'previewer': '/static/js/capa/chemical_equation_preview.js', 'previewer': '/static/js/capa/chemical_equation_preview.js',
} }
......
...@@ -1995,7 +1995,7 @@ cktsim = (function() { ...@@ -1995,7 +1995,7 @@ cktsim = (function() {
// set up each schematic entry widget // set up each schematic entry widget
function update_schematics() { function update_schematics() {
// set up each schematic on the page // set up each schematic on the page
var schematics = document.getElementsByClassName('schematic'); var schematics = $('.schematic');
for (var i = 0; i < schematics.length; ++i) for (var i = 0; i < schematics.length; ++i)
if (schematics[i].getAttribute("loaded") != "true") { if (schematics[i].getAttribute("loaded") != "true") {
try { try {
...@@ -2036,7 +2036,7 @@ function add_schematic_handler(other_onload) { ...@@ -2036,7 +2036,7 @@ function add_schematic_handler(other_onload) {
// ask each schematic input widget to update its value field for submission // ask each schematic input widget to update its value field for submission
function prepare_schematics() { function prepare_schematics() {
var schematics = document.getElementsByClassName('schematic'); var schematics = $('.schematic');
for (var i = schematics.length - 1; i >= 0; i--) for (var i = schematics.length - 1; i >= 0; i--)
schematics[i].schematic.update_value(); schematics[i].schematic.update_value();
} }
...@@ -3339,23 +3339,28 @@ schematic = (function() { ...@@ -3339,23 +3339,28 @@ schematic = (function() {
} }
// add method to canvas to compute relative coords for event // add method to canvas to compute relative coords for event
HTMLCanvasElement.prototype.relMouseCoords = function(event){ try {
// run up the DOM tree to figure out coords for top,left of canvas if (HTMLCanvasElement)
var totalOffsetX = 0; HTMLCanvasElement.prototype.relMouseCoords = function(event){
var totalOffsetY = 0; // run up the DOM tree to figure out coords for top,left of canvas
var currentElement = this; var totalOffsetX = 0;
do { var totalOffsetY = 0;
totalOffsetX += currentElement.offsetLeft; var currentElement = this;
totalOffsetY += currentElement.offsetTop; do {
} totalOffsetX += currentElement.offsetLeft;
while (currentElement = currentElement.offsetParent); totalOffsetY += currentElement.offsetTop;
}
// now compute relative position of click within the canvas while (currentElement = currentElement.offsetParent);
this.mouse_x = event.pageX - totalOffsetX;
this.mouse_y = event.pageY - totalOffsetY; // now compute relative position of click within the canvas
this.mouse_x = event.pageX - totalOffsetX;
this.page_x = event.pageX; this.mouse_y = event.pageY - totalOffsetY;
this.page_y = event.pageY;
this.page_x = event.pageX;
this.page_y = event.pageY;
}
}
catch (err) { // ignore
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -3718,7 +3723,7 @@ schematic = (function() { ...@@ -3718,7 +3723,7 @@ schematic = (function() {
// look for property input fields in the content and give // look for property input fields in the content and give
// them a keypress listener that interprets ENTER as // them a keypress listener that interprets ENTER as
// clicking OK. // clicking OK.
var plist = content.getElementsByClassName('property'); var plist = content.$('.property');
for (var i = plist.length - 1; i >= 0; --i) { for (var i = plist.length - 1; i >= 0; --i) {
var field = plist[i]; var field = plist[i];
field.dialog = dialog; // help event handler find us... field.dialog = dialog; // help event handler find us...
...@@ -4091,48 +4096,52 @@ schematic = (function() { ...@@ -4091,48 +4096,52 @@ schematic = (function() {
// add dashed lines! // add dashed lines!
// from http://davidowens.wordpress.com/2010/09/07/html-5-canvas-and-dashed-lines/ // from http://davidowens.wordpress.com/2010/09/07/html-5-canvas-and-dashed-lines/
CanvasRenderingContext2D.prototype.dashedLineTo = function(fromX, fromY, toX, toY, pattern) { try {
// Our growth rate for our line can be one of the following: if (CanvasRenderingContext2D)
// (+,+), (+,-), (-,+), (-,-) CanvasRenderingContext2D.prototype.dashedLineTo = function(fromX, fromY, toX, toY, pattern) {
// Because of this, our algorithm needs to understand if the x-coord and // Our growth rate for our line can be one of the following:
// y-coord should be getting smaller or larger and properly cap the values // (+,+), (+,-), (-,+), (-,-)
// based on (x,y). // Because of this, our algorithm needs to understand if the x-coord and
var lt = function (a, b) { return a <= b; }; // y-coord should be getting smaller or larger and properly cap the values
var gt = function (a, b) { return a >= b; }; // based on (x,y).
var capmin = function (a, b) { return Math.min(a, b); }; var lt = function (a, b) { return a <= b; };
var capmax = function (a, b) { return Math.max(a, b); }; var gt = function (a, b) { return a >= b; };
var capmin = function (a, b) { return Math.min(a, b); };
var checkX = { thereYet: gt, cap: capmin }; var capmax = function (a, b) { return Math.max(a, b); };
var checkY = { thereYet: gt, cap: capmin };
var checkX = { thereYet: gt, cap: capmin };
if (fromY - toY > 0) { var checkY = { thereYet: gt, cap: capmin };
checkY.thereYet = lt;
checkY.cap = capmax; if (fromY - toY > 0) {
} checkY.thereYet = lt;
if (fromX - toX > 0) { checkY.cap = capmax;
checkX.thereYet = lt; }
checkX.cap = capmax; if (fromX - toX > 0) {
} checkX.thereYet = lt;
checkX.cap = capmax;
this.moveTo(fromX, fromY); }
var offsetX = fromX;
var offsetY = fromY; this.moveTo(fromX, fromY);
var idx = 0, dash = true; var offsetX = fromX;
while (!(checkX.thereYet(offsetX, toX) && checkY.thereYet(offsetY, toY))) { var offsetY = fromY;
var ang = Math.atan2(toY - fromY, toX - fromX); var idx = 0, dash = true;
var len = pattern[idx]; while (!(checkX.thereYet(offsetX, toX) && checkY.thereYet(offsetY, toY))) {
var ang = Math.atan2(toY - fromY, toX - fromX);
offsetX = checkX.cap(toX, offsetX + (Math.cos(ang) * len)); var len = pattern[idx];
offsetY = checkY.cap(toY, offsetY + (Math.sin(ang) * len));
offsetX = checkX.cap(toX, offsetX + (Math.cos(ang) * len));
if (dash) this.lineTo(offsetX, offsetY); offsetY = checkY.cap(toY, offsetY + (Math.sin(ang) * len));
else this.moveTo(offsetX, offsetY);
if (dash) this.lineTo(offsetX, offsetY);
idx = (idx + 1) % pattern.length; else this.moveTo(offsetX, offsetY);
dash = !dash;
} idx = (idx + 1) % pattern.length;
}; dash = !dash;
}
};
}
catch (err) { //noop
}
// given a range of values, return a new range [vmin',vmax'] where the limits // given a range of values, return a new range [vmin',vmax'] where the limits
// have been chosen "nicely". Taken from matplotlib.ticker.LinearLocator // have been chosen "nicely". Taken from matplotlib.ticker.LinearLocator
function view_limits(vmin,vmax) { function view_limits(vmin,vmax) {
......
...@@ -176,6 +176,33 @@ class ImportTestCase(unittest.TestCase): ...@@ -176,6 +176,33 @@ class ImportTestCase(unittest.TestCase):
self.assertEqual(chapter_xml.tag, 'chapter') self.assertEqual(chapter_xml.tag, 'chapter')
self.assertFalse('graceperiod' in chapter_xml.attrib) self.assertFalse('graceperiod' in chapter_xml.attrib)
def test_is_pointer_tag(self):
"""
Check that is_pointer_tag works properly.
"""
yes = ["""<html url_name="blah"/>""",
"""<html url_name="blah"></html>""",
"""<html url_name="blah"> </html>""",
"""<problem url_name="blah"/>""",
"""<course org="HogwartsX" course="Mathemagics" url_name="3.14159"/>"""]
no = ["""<html url_name="blah" also="this"/>""",
"""<html url_name="blah">some text</html>""",
"""<problem url_name="blah"><sub>tree</sub></problem>""",
"""<course org="HogwartsX" course="Mathemagics" url_name="3.14159">
<chapter>3</chapter>
</course>
"""]
for xml_str in yes:
print "should be True for {0}".format(xml_str)
self.assertTrue(is_pointer_tag(etree.fromstring(xml_str)))
for xml_str in no:
print "should be False for {0}".format(xml_str)
self.assertFalse(is_pointer_tag(etree.fromstring(xml_str)))
def test_metadata_inherit(self): def test_metadata_inherit(self):
"""Make sure that metadata is inherited properly""" """Make sure that metadata is inherited properly"""
...@@ -311,3 +338,5 @@ class ImportTestCase(unittest.TestCase): ...@@ -311,3 +338,5 @@ class ImportTestCase(unittest.TestCase):
system = self.get_system(False) system = self.get_system(False)
self.assertRaises(etree.XMLSyntaxError, system.process_xml, bad_xml) self.assertRaises(etree.XMLSyntaxError, system.process_xml, bad_xml)
...@@ -25,7 +25,7 @@ def name_to_pathname(name): ...@@ -25,7 +25,7 @@ def name_to_pathname(name):
def is_pointer_tag(xml_obj): def is_pointer_tag(xml_obj):
""" """
Check if xml_obj is a pointer tag: <blah url_name="something" />. Check if xml_obj is a pointer tag: <blah url_name="something" />.
No children, one attribute named url_name. No children, one attribute named url_name, no text.
Special case for course roots: the pointer is Special case for course roots: the pointer is
<course url_name="something" org="myorg" course="course"> <course url_name="something" org="myorg" course="course">
...@@ -40,7 +40,10 @@ def is_pointer_tag(xml_obj): ...@@ -40,7 +40,10 @@ def is_pointer_tag(xml_obj):
expected_attr = set(['url_name', 'course', 'org']) expected_attr = set(['url_name', 'course', 'org'])
actual_attr = set(xml_obj.attrib.keys()) actual_attr = set(xml_obj.attrib.keys())
return len(xml_obj) == 0 and actual_attr == expected_attr
has_text = xml_obj.text is not None and len(xml_obj.text.strip()) > 0
return len(xml_obj) == 0 and actual_attr == expected_attr and not has_text
def get_metadata_from_xml(xml_object, remove=True): def get_metadata_from_xml(xml_object, remove=True):
meta = xml_object.find('meta') meta = xml_object.find('meta')
......
...@@ -105,7 +105,7 @@ NUMPY_VER="1.6.2" ...@@ -105,7 +105,7 @@ NUMPY_VER="1.6.2"
SCIPY_VER="0.10.1" SCIPY_VER="0.10.1"
BREW_FILE="$BASE/mitx/brew-formulas.txt" BREW_FILE="$BASE/mitx/brew-formulas.txt"
LOG="/var/tmp/install-$(date +%Y%m%d-%H%M%S).log" LOG="/var/tmp/install-$(date +%Y%m%d-%H%M%S).log"
APT_PKGS="pkg-config curl git python-virtualenv build-essential python-dev gfortran liblapack-dev libfreetype6-dev libpng12-dev libxml2-dev libxslt-dev yui-compressor coffeescript graphviz graphviz-dev" APT_PKGS="pkg-config curl git python-virtualenv build-essential python-dev gfortran liblapack-dev libfreetype6-dev libpng12-dev libxml2-dev libxslt-dev yui-compressor coffeescript graphviz graphviz-dev mysql-server libmysqlclient-dev"
if [[ $EUID -eq 0 ]]; then if [[ $EUID -eq 0 ]]; then
error "This script should not be run using sudo or as the root user" error "This script should not be run using sudo or as the root user"
...@@ -193,7 +193,8 @@ case `uname -s` in ...@@ -193,7 +193,8 @@ case `uname -s` in
maya|lisa|natty|oneiric|precise|quantal) maya|lisa|natty|oneiric|precise|quantal)
output "Installing ubuntu requirements" output "Installing ubuntu requirements"
sudo apt-get -y update sudo apt-get -y update
sudo apt-get -y install $APT_PKGS # DEBIAN_FRONTEND=noninteractive is required for silent mysql-server installation
sudo DEBIAN_FRONTEND=noninteractive apt-get -y install $APT_PKGS
clone_repos clone_repos
;; ;;
*) *)
......
# Notes on using mongodb backed LMS and CMS
These are some random notes for developers, on how things are stored in mongodb, and how to debug mongodb data.
## Databases
Two mongodb databases are used:
- xmodule: stores module definitions and metadata (modulestore)
- xcontent: stores filesystem content, like PDF files
modulestore documents are stored with an _id which has fields like this:
{"_id": {"tag":"i4x","org":"HarvardX","course":"CS50x","category":"chapter","name":"Week_1","revision":null}}
## Document fields
### Problems
Here is an example showing the fields available in problem documents:
{
"_id" : {
"tag" : "i4x",
"org" : "MITx",
"course" : "6.00x",
"category" : "problem",
"name" : "ps03:ps03-Hangman_part_2_The_Game",
"revision" : null
},
"definition" : {
"data" : " ..."
},
"metadata" : {
"display_name" : "Hangman Part 2: The Game",
"attempts" : "30",
"title" : "Hangman, Part 2",
"data_dir" : "6.00x",
"type" : "lecture"
}
}
## Sample interaction with mongodb
1. "mongo"
2. "use xmodule"
3. "show collections" should give "modulestore" and "system.indexes"
4. 'db.modulestore.find( {"_id.org": "MITx"} )' will produce a list of all MITx course documents
5. 'db.modulestore.find( {"_id.org": "MITx", "_id.category": "problem"} )' will produce a list of all problems in MITx courses
Example query for finding all files with "image" in the filename:
- use xcontent
- db.fs.files.find({'filename': /image/ } )
- db.fs.files.find({'filename': /image/ } ).count()
## Debugging the mongodb contents
A convenient tool is http://phpmoadmin.com/ (needs php)
Under ubuntu, do:
- apt-get install php5-fpm php-pear
- pecl install mongo
- edit /etc/php5/fpm/php.ini to add "extension=mongo.so"
- /etc/init.d/php5-fpm restart
and also setup nginx to run php through fastcgi.
## Backing up mongodb
- mogodump (dumps all dbs)
- mongodump --collection modulestore --db xmodule (dumps just xmodule/modulestore)
- mongodump -d xmodule -q '{"_id.org": "MITx"}' (dumps just MITx documents in xmodule)
- mongodump -q '{"_id.org": "MITx"}' (dumps all MITx documents)
## Deleting course content
Use "remove" instead of "find":
- db.modulestore.remove( {"_id.course": "8.01greytak"})
## Finding useful information from the mongodb modulestore
- Organizations
> db.modulestore.distinct( "_id.org")
[ "HarvardX", "MITx", "edX", "edx" ]
- Courses
> db.modulestore.distinct( "_id.course")
[
"CS50x",
"PH207x",
"3.091x",
"6.002x",
"6.00x",
"8.01esg",
"8.01rq_MW",
"8.02teal",
"8.02x",
"edx4edx",
"toy",
"templates"
]
- Find a problem which has the word "quantum" in its definition
db.modulestore.findOne( {"definition.data":/quantum/})n
- Find Location for all problems with the word "quantum" in its definition
db.modulestore.find( {"definition.data":/quantum/}, {'_id':1})
- Number of problems in each course
db.runCommand({
mapreduce: "modulestore",
query: { '_id.category': 'problem' },
map: function(){ emit(this._id.course, {count:1}); },
reduce: function(key, values){
var result = {count:0};
values.forEach(function(value) {
result.count += value.count;
});
return result;
},
out: 'pbyc',
verbose: true
});
produces:
> db.pbyc.find()
{ "_id" : "3.091x", "value" : { "count" : 184 } }
{ "_id" : "6.002x", "value" : { "count" : 176 } }
{ "_id" : "6.00x", "value" : { "count" : 147 } }
{ "_id" : "8.01esg", "value" : { "count" : 184 } }
{ "_id" : "8.01rq_MW", "value" : { "count" : 73 } }
{ "_id" : "8.02teal", "value" : { "count" : 5 } }
{ "_id" : "8.02x", "value" : { "count" : 99 } }
{ "_id" : "PH207x", "value" : { "count" : 25 } }
{ "_id" : "edx4edx", "value" : { "count" : 50 } }
{ "_id" : "templates", "value" : { "count" : 11 } }
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MITx.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MITx.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/MITx"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/MITx"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
{% extends "!layout.html" %}
{% block header %}
<img src="{{ pathto("_static/homepage-bg.jpg", 1) }}" alt="Edx logo" width="100%;"/>
{% endblock %}
\ No newline at end of file
*******************************************
Capa module
*******************************************
.. module:: capa
Calc
====
.. automodule:: capa.calc
:members:
:show-inheritance:
Capa_problem
============
.. automodule:: capa.capa_problem
:members:
:show-inheritance:
Checker
=======
.. automodule:: capa.checker
:members:
:show-inheritance:
Correctmap
==========
.. automodule:: capa.correctmap
:members:
:show-inheritance:
Customrender
============
.. automodule:: capa.customrender
:members:
:show-inheritance:
Inputtypes
==========
.. automodule:: capa.inputtypes
:members:
:show-inheritance:
Resposetypes
============
.. automodule:: capa.responsetypes
:members:
:show-inheritance:
*******************************************
CMS module
*******************************************
.. module:: cms
Auth
====
.. automodule:: auth
:members:
:show-inheritance:
Authz
-----
.. automodule:: auth.authz
:members:
:show-inheritance:
Content store
=============
.. .. automodule:: contentstore
.. :members:
.. :show-inheritance:
.. Utils
.. -----
.. .. automodule:: contentstore.untils
.. :members:
.. :show-inheritance:
.. Views
.. -----
.. .. automodule:: contentstore.views
.. :members:
.. :show-inheritance:
.. Management
.. ----------
.. .. automodule:: contentstore.management
.. :members:
.. :show-inheritance:
.. Tests
.. -----
.. .. automodule:: contentstore.tests
.. :members:
.. :show-inheritance:
Github sync
===========
.. automodule:: github_sync
:members:
:show-inheritance:
Exceptions
----------
.. automodule:: github_sync.exceptions
:members:
:show-inheritance:
Views
-----
.. automodule:: github_sync.views
:members:
:show-inheritance:
Management
----------
.. automodule:: github_sync.management
:members:
:show-inheritance:
Tests
-----
.. .. automodule:: github_sync.tests
.. :members:
.. :show-inheritance:
\ No newline at end of file
Common / lib
===============================
Contents:
.. toctree::
:maxdepth: 2
xmodule.rst
capa.rst
\ No newline at end of file
*******************************************
Common
*******************************************
.. module:: common.djangoapps
Student
=======
.. automodule:: student
:members:
:show-inheritance:
Models
------
.. automodule:: student.models
:members:
:show-inheritance:
Views
-----
.. automodule:: student.views
:members:
:show-inheritance:
Admin
-----
.. automodule:: student.admin
:members:
:show-inheritance:
Tests
-----
.. automodule:: student.tests
:members:
:show-inheritance:
Management
----------
.. automodule:: student.management
:members:
:show-inheritance:
Migrations
----------
.. automodule:: student.migrations
:members:
:show-inheritance:
\ No newline at end of file
Django applications
===============================
Contents:
.. toctree::
:maxdepth: 2
lms.rst
cms.rst
djangoapps-common.rst
\ No newline at end of file
.. MITx documentation master file, created by
sphinx-quickstart on Fri Nov 2 15:43:00 2012.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to MITx's documentation!
================================
Contents:
.. toctree::
:maxdepth: 2
overview.rst
common-lib.rst
djangoapps.rst
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
*******************************************
LMS module
*******************************************
.. module:: lms
Branding
========
.. automodule:: branding
:members:
:show-inheritance:
Views
-----
.. automodule:: branding.views
:members:
:show-inheritance:
Certificates
============
.. automodule:: certificates
:members:
:show-inheritance:
Models
------
.. automodule:: certificates.models
:members:
:show-inheritance:
Views
-----
.. automodule:: certificates.views
:members:
:show-inheritance:
Tests
-----
.. automodule:: certificates.tests
:members:
:show-inheritance:
Circuit
=======
.. automodule:: circuit
:members:
:show-inheritance:
Models
------
.. automodule:: circuit.models
:members:
:show-inheritance:
Views
-----
.. automodule:: circuit.views
:members:
:show-inheritance:
Tests
-----
.. automodule:: circuit.tests
:members:
:show-inheritance:
Course_wiki
===========
.. automodule:: course_wiki
:members:
:show-inheritance:
Course Nav
----------
.. .. automodule:: course_wiki.course_nav
.. :members:
.. :show-inheritance:
Views
-----
.. automodule:: course_wiki.views
:members:
:show-inheritance:
Editors
-------
.. automodule:: course_wiki.editors
:members:
:show-inheritance:
Courseware
==========
.. automodule:: courseware
:members:
:show-inheritance:
Access
------
.. automodule:: courseware.access
:members:
:show-inheritance:
Admin
-----
.. automodule:: courseware.admin
:members:
:show-inheritance:
Courses
-------
.. automodule:: courseware.courses
:members:
:show-inheritance:
Grades
------
.. automodule:: courseware.grades
:members:
:show-inheritance:
Models
------
.. automodule:: courseware.models
:members:
:show-inheritance:
Progress
--------
.. automodule:: courseware.progress
:members:
:show-inheritance:
Tabs
----
.. automodule:: courseware.tabs
:members:
:show-inheritance:
Dashboard
=========
.. automodule:: dashboard
:members:
:show-inheritance:
Models
------
.. automodule:: dashboard.models
:members:
:show-inheritance:
Views
-----
.. automodule:: dashboard.views
:members:
:show-inheritance:
Tests
-----
.. automodule:: dashboard.tests
:members:
:show-inheritance:
Django comment client
=====================
.. automodule:: django_comment_client
:members:
:show-inheritance:
Models
------
.. automodule:: django_comment_client.models
:members:
:show-inheritance:
Tests
-----
.. automodule:: django_comment_client.tests
:members:
:show-inheritance:
Heartbeat
=========
.. automodule:: heartbeat
:members:
:show-inheritance:
Instructor
==========
.. automodule:: instructor
:members:
:show-inheritance:
Views
-----
.. automodule:: instructor.views
:members:
:show-inheritance:
Tests
-----
.. .. automodule:: instructor.tests
.. :members:
.. :show-inheritance:
Lisenses
========
.. automodule:: licenses
:members:
:show-inheritance:
Models
------
.. automodule:: licenses.models
:members:
:show-inheritance:
Views
-----
.. automodule:: licenses.views
:members:
:show-inheritance:
Tests
-----
.. automodule:: licenses.tests
:members:
:show-inheritance:
LMS migration
=============
.. automodule:: lms_migration
:members:
:show-inheritance:
Migration
---------
.. automodule:: lms_migration.migrate
:members:
:show-inheritance:
Multicourse
===========
.. automodule:: multicourse
:members:
:show-inheritance:
Psychometrics
=============
.. automodule:: psychometrics
:members:
:show-inheritance:
Models
------
.. automodule:: psychometrics.models
:members:
:show-inheritance:
Admin
-----
.. automodule:: psychometrics.admin
:members:
:show-inheritance:
Psychoanalyze
-------------
.. automodule:: psychometrics.psychoanalyze
:members:
:show-inheritance:
Simple wiki
===========
.. automodule:: simplewiki
:members:
:show-inheritance:
Models
------
.. automodule:: simplewiki.models
:members:
:show-inheritance:
Views
-----
.. automodule:: simplewiki.views
:members:
:show-inheritance:
Tests
-----
.. automodule:: simplewiki.tests
:members:
:show-inheritance:
Static template view
====================
.. automodule:: static_template_view
:members:
:show-inheritance:
Models
------
.. automodule:: static_template_view.models
:members:
:show-inheritance:
Views
-----
.. automodule:: static_template_view.views
:members:
:show-inheritance:
Tests
-----
.. automodule:: static_template_view.tests
:members:
:show-inheritance:
Static book
===========
.. automodule:: staticbook
:members:
:show-inheritance:
Models
------
.. automodule:: staticbook.models
:members:
:show-inheritance:
Views
-----
.. automodule:: staticbook.views
:members:
:show-inheritance:
Tests
-----
.. automodule:: staticbook.tests
:members:
:show-inheritance:
*******************************************
What the pieces are?
*******************************************
What
====
...
How
===
...
Who
===
...
\ No newline at end of file
*******************************************
Xmodule
*******************************************
.. module:: xmodule
Abtest
======
.. automodule:: xmodule.abtest_module
:members:
:show-inheritance:
Back compatibility
==================
.. automodule:: xmodule.backcompat_module
:members:
:show-inheritance:
Capa
====
.. automodule:: xmodule.capa_module
:members:
:show-inheritance:
Course
======
.. automodule:: xmodule.course_module
:members:
:show-inheritance:
Discussion
==========
.. automodule:: xmodule.discussion_module
:members:
:show-inheritance:
Editing
=======
.. automodule:: xmodule.editing_module
:members:
:show-inheritance:
Error
=====
.. automodule:: xmodule.error_module
:members:
:show-inheritance:
Error tracker
=============
.. automodule:: xmodule.errortracker
:members:
:show-inheritance:
Exceptions
==========
.. automodule:: xmodule.exceptions
:members:
:show-inheritance:
Graders
=======
.. automodule:: xmodule.graders
:members:
:show-inheritance:
Hidden
======
.. automodule:: xmodule.hidden_module
:members:
:show-inheritance:
Html checker
============
.. automodule:: xmodule.html_checker
:members:
:show-inheritance:
Html
====
.. automodule:: xmodule.html_module
:members:
:show-inheritance:
Mako
====
.. automodule:: xmodule.mako_module
:members:
:show-inheritance:
Progress
========
.. automodule:: xmodule.progress
:members:
:show-inheritance:
Schematic
=========
.. automodule:: xmodule.schematic_module
:members:
:show-inheritance:
Sequence
========
.. automodule:: xmodule.seq_module
:members:
:show-inheritance:
Stringify
=========
.. automodule:: xmodule.stringify
:members:
:show-inheritance:
Template
========
.. automodule:: xmodule.template_module
:members:
:show-inheritance:
Templates
=========
.. automodule:: xmodule.templates
:members:
:show-inheritance:
Time parse
==========
.. automodule:: xmodule.timeparse
:members:
:show-inheritance:
Vertical
========
.. automodule:: xmodule.vertical_module
:members:
:show-inheritance:
Video
=====
.. automodule:: xmodule.video_module
:members:
:show-inheritance:
X
=
.. automodule:: xmodule.x_module
:members:
:show-inheritance:
Xml
===
.. automodule:: xmodule.xml_module
:members:
:show-inheritance:
...@@ -217,6 +217,7 @@ def index(request, course_id, chapter=None, section=None, ...@@ -217,6 +217,7 @@ def index(request, course_id, chapter=None, section=None,
'init': '', 'init': '',
'content': '', 'content': '',
'staff_access': staff_access, 'staff_access': staff_access,
'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER','http://xqa:server@content-qa.mitx.mit.edu/xqa')
} }
chapter_descriptor = course.get_child_by_url_name(chapter) chapter_descriptor = course.get_child_by_url_name(chapter)
......
...@@ -19,7 +19,7 @@ class PermissionsTestCase(TestCase): ...@@ -19,7 +19,7 @@ class PermissionsTestCase(TestCase):
def setUp(self): def setUp(self):
self.course_id = "MITx/6.002x/2012_Fall" self.course_id = "edX/toy/2012_Fall"
self.moderator_role = Role.objects.get_or_create(name="Moderator", course_id=self.course_id)[0] self.moderator_role = Role.objects.get_or_create(name="Moderator", course_id=self.course_id)[0]
self.student_role = Role.objects.get_or_create(name="Student", course_id=self.course_id)[0] self.student_role = Role.objects.get_or_create(name="Student", course_id=self.course_id)[0]
......
...@@ -33,3 +33,13 @@ CONTENTSTORE = { ...@@ -33,3 +33,13 @@ CONTENTSTORE = {
'db': 'xcontent', 'db': 'xcontent',
} }
} }
INSTALLED_APPS += (
# Mongo perf stats
'debug_toolbar_mongo',
)
DEBUG_TOOLBAR_PANELS += (
'debug_toolbar_mongo.panel.MongoDebugPanel',
)
...@@ -25,7 +25,9 @@ ...@@ -25,7 +25,9 @@
<%static:js group='discussion'/> <%static:js group='discussion'/>
<%include file="../discussion/_js_body_dependencies.html" /> <%include file="../discussion/_js_body_dependencies.html" />
% if staff_access:
<%include file="xqa_interface.html"/>
% endif
<!-- TODO: http://docs.jquery.com/Plugins/Validation --> <!-- TODO: http://docs.jquery.com/Plugins/Validation -->
<script type="text/javascript"> <script type="text/javascript">
......
<script type="text/javascript" src="/static/js/vendor/jquery.leanModal.min.js"></script>
<script type="text/javascript">
function setup_debug(element_id, edit_link, staff_context){
$('#' + element_id + '_trig').leanModal();
$('#' + element_id + '_xqa_log').leanModal();
$('#' + element_id + '_xqa_form').submit(function () {sendlog(element_id, edit_link, staff_context);});
}
function sendlog(element_id, edit_link, staff_context){
var xqaLog = {
authkey: staff_context.xqa_key,
location: staff_context.location,
category : staff_context.category,
'username' : staff_context.user.username,
return : 'query',
format : 'html',
email : staff_context.user.email,
tag:$('#' + element_id + '_xqa_tag').val(),
entry: $('#' + element_id + '_xqa_entry').val()
};
if (edit_link) xqaLog["giturl"] = edit_link;
$.ajax({
url: '${xqa_server}/log',
type: 'GET',
contentType: 'application/json',
data: JSON.stringify(xqaLog),
crossDomain: true,
dataType: 'jsonp',
beforeSend: function (xhr) {
xhr.setRequestHeader ("Authorization", "Basic eHFhOmFnYXJ3YWw="); },
timeout : 1000,
success: function(result) {
$('#' + element_id + '_xqa_log_data').html(result);
},
error: function() {
alert('Error: cannot connect to XQA server');
console.log('error!');
}
});
return false;
};
function getlog(element_id, staff_context){
var xqaQuery = {
authkey: staff_context.xqa_key,
location: staff_context.location,
format: 'html'
};
$.ajax({
url: '${xqa_server}/query',
type: 'GET',
contentType: 'application/json',
data: JSON.stringify(xqaQuery),
crossDomain: true,
dataType: 'jsonp',
timeout : 1000,
success: function(result) {
$('#' + element_id + '_xqa_log_data').html(result);
},
error: function() {
alert('Error: cannot connect to XQA server');
}
});
};
</script>
\ No newline at end of file
${module_content} ${module_content}
%if edit_link: %if edit_link:
<div><a href="${edit_link}">Edit</a> / <a href="#${element_id}_xqa-modal" onclick="getlog_${element_id}()" id="${element_id}_xqa_log">QA</a></div> <div>
<a href="${edit_link}">Edit</a> /
<a href="#${element_id}_xqa-modal" onclick="javascript:getlog('${element_id}', {
'location': '${location}',
'xqa_key': '${xqa_key}',
'category': '${category}',
'user': '${user}'
})" id="${element_id}_xqa_log">QA</a>
</div>
% endif % endif
<div><a href="#${element_id}_debug" id="${element_id}_trig">Staff Debug Info</a></div> <div><a href="#${element_id}_debug" id="${element_id}_trig">Staff Debug Info</a></div>
...@@ -50,77 +58,19 @@ category = ${category | h} ...@@ -50,77 +58,19 @@ category = ${category | h}
<div id="${element_id}_setup"></div> <div id="${element_id}_setup"></div>
## leanModal needs to be included here otherwise this breaks when in a <vertical>
<script type="text/javascript" src="/static/js/vendor/jquery.leanModal.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
// assumes courseware.html's loaded this method.
function setup_debug_${element_id}(){ setup_debug('${element_id}',
$('#${element_id}_trig').leanModal(); %if edit_link:
$('#${element_id}_xqa_log').leanModal(); '${edit_link}',
$('#${element_id}_xqa_form').submit(sendlog_${element_id}); %else:
} null,
%endif
setup_debug_${element_id}(); {
'location': '${location}',
function sendlog_${element_id}(){ 'xqa_key': '${xqa_key}',
'category': '${category}',
var xqaLog = {authkey: '${xqa_key}', 'user': '${user}'
location: '${location}', });
%if edit_link:
giturl: '${edit_link}',
%endif
category : '${category}',
username : '${user.username}',
return : 'query',
format : 'html',
email : '${user.email}',
tag:$('#${element_id}_xqa_tag').val(),
entry: $('#${element_id}_xqa_entry').val()};
$.ajax({
url: '${xqa_server}/log',
type: 'GET',
contentType: 'application/json',
data: JSON.stringify(xqaLog),
crossDomain: true,
dataType: 'jsonp',
beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", "Basic eHFhOmFnYXJ3YWw="); },
timeout : 1000,
success: function(result) {
$('#${element_id}_xqa_log_data').html(result);
},
error: function() {
alert('Error: cannot connect to XQA server');
console.log('error!');
}
});
return false;
};
function getlog_${element_id}(){
var xqaQuery = {authkey: '${xqa_key}',
location: '${location}',
format: 'html'};
$.ajax({
url: '${xqa_server}/query',
type: 'GET',
contentType: 'application/json',
data: JSON.stringify(xqaQuery),
crossDomain: true,
dataType: 'jsonp',
timeout : 1000,
success: function(result) {
$('#${element_id}_xqa_log_data').html(result);
},
error: function() {
alert('Error: cannot connect to XQA server');
}
});
};
</script> </script>
...@@ -30,99 +30,20 @@ ...@@ -30,99 +30,20 @@
<hr class="horizontal-divider"> <hr class="horizontal-divider">
<section class="jobs-wrapper"> <section class="jobs-wrapper">
<section class="jobs-listing"> <section class="jobs-listing">
<article id="content-engineer" class="job"> <article id="" class="job">
<div class="inner-wrapper"> <div class="inner-wrapper">
<h3>EdX Content Engineer</h3> <h3>We're hiring! </h3>
<p>Content Engineers support edX Fellows and edX Course Managers in the overall technical development of course content, assessments, and domain-specific online tools. Tasks include developing graders for rich problems, designing automated tools for import of problems from other formats, as well as creating new ways for students to interact with domain-specific problems in the system.</p> <p>Are you passionate? Want to help change the world? Good, you've found the right company! We're growing and our team needs the best and brightest in creating the next evolution in interactive online education.</p>
<p>A candidate must have:</p> <h4>Want to apply to edX?</h4>
<ul> <p>Send your resume and cover letter to <a href="mailto:jobs@edx.org">jobs@edx.org</a>.</p>
<li>Python or JavaScript development experience</li> <p><em>Note:</em> We'll review each and every resume but please note you may not get a response due to the volume of inquiries.</p>
<li>A deep interest in pedagogy and education</li>
</ul>
<p>Knowledge of GWT or Backbone.js a plus.</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>
<article id="platform-developer" class="job">
<div class="inner-wrapper">
<h3>Platform Developer</h3>
<p>Platform Developers build the core learning platform that powers edX, writing both front-end and back-end code. They tackle a wide range of technical challenges, and so the best candidates will have a strong background in one or more of the following areas: machine learning, education, user interaction design, big data, social network analysis, and devops. Specialists are encouraged to apply, but team members often wear many hats. Our ideal candidate would have excellent coding skills, a proven history of delivering projects, and a deep research background.</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>
<article id="learning-designer" class="job">
<div class="inner-wrapper">
<h3>Learning Designer/Interaction Learning Designer </h3>
<p>The Learning Designer will work as part of the content and development team to plan, develop and deliver highly engaging and media rich online courses. The learning designer will be a flexible thinker, able to determine and apply sound pedagogical strategies to unique situations and a diverse set of academic disciplines. This is a 6-12 months contract opportunity.</p>
<h4>Specific Responsibilities include: </h4>
<ul>
<li>Work with producers, product developers and course staff on implementing instructional design approaches in the development of media and other course materials. </li>
<li>Articulate learning objectives and align them to content design strategy and assessments. </li>
<li>Write effective instructional text, and audio and video scripts. </li>
<li>Coordinate workflows with video and content development team</li>
<li>Identify best practices and share these with the course staff and faculty as needed. </li>
<li>Create course communication style guides. Train and coach teaching staff on best practices for communication and discussion management. </li>
<li>Develop use case guides as needed on the use of edX courseware and new technologies. </li>
<li>Serve as a liaison to instructional design teams located at X universities. </li>
<li>Design peer review processes to be used by learners in selected courses. </li>
<li>Ability to apply game-based learning theory and design into selected courses as appropriate.</li>
<li>Use learning analytics and metrics to inform course design and revision process. </li>
<li>Work closely with the Content Research Director on articulating best practices for MOOC teaching and learning and course design.</li>
<li>Assist in the development of pilot courses used for sponsored research initiatives. </li>
</ul>
<h4>Qualifications:</h4>
<p>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 desirable. 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. Ability to meet deadlines and manage expectations of constituents. Capacity to develop new and relevant technology skills. &nbsp;Experience using game theory design and learning analytics to inform instructional design decisions and strategy.</p>
<h4>Technical Skills:</h4>
<p>Video and screencasting experience. LMS Platform experience, xml, HTML, CSS, Adobe Design Suite, Camtasia or Captivate experience. Experience with web 2.0 collaboration tools.</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>
<article id="production-coordinator" class="job">
<div class="inner-wrapper">
<h3>Production Coordinator</h3>
<p>The Production Coordinator supports video editors and course staff in all video related tasks, such as ingesting footage, transcoding, tracking live dates, transcriptions, organizing project deliverables and archiving completed projects.</p>
<h4>Primary responsibilities:</h4>
<ul>
<li>organize, track, and manage video and associated assets across the video workflow</li>
<li>manage project data and spreadsheets</li>
<li>route incoming source footage, and apply metadata tags</li>
<li>run encoding/transcoding jobs </li>
<li>prepare and process associated video assets, such as slides and image files</li>
<li>manage the transcription process </li>
<ul type="circle">
<li>traffic files among project staff and video transcription services</li>
<li>coordinate transcript reviews with course staff</li>
<li>integrate transcripts in course pages</li>
</ul>
<li>other video-related tasks as assigned.</li>
</ul>
<br/>
<h4>Qualifications</h4>
<p>The ideal candidate for the Production Coordinator position will have</p>
<ul>
<li>relentless attention to detail</li>
<li>ability to communicate and collaborate effectively across the organization</li>
<li>knowledge and understanding of digital media production tools and processes</li>
<li>experience with compression techniques, image processing, and presentation software preferred</li>
<li>proficiency with standard office applications </li>
<ul type="circle">
<li>spreadsheets</li>
<li>word processing</li>
<li>presentation</li>
</ul>
<li>experience with web publishing, e.g., HTML, XML, CSS, a plus</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>
</section> </section>
<section class="jobs-sidebar"> <section class="jobs-sidebar">
<h2>Positions</h2> <!-- <h2>Positions</h2> -->
<nav> <!-- <nav> -->
<a href="#content-engineer">EdX Content Engineer</a> <!-- <a href="#content-engineer">EdX Content Engineer</a> -->
<a href="#platform-developer">Platform Developer</a> <!-- </nav> -->
<a href="#learning-designer">Learning Designer</a>
<a href="#production-coordinator">Production Coordinator</a>
</nav>
<h2>How to Apply</h2> <h2>How to Apply</h2>
<p>E-mail your resume, coverletter and any other materials to <a href="mailto:jobs@edx.org">jobs@edx.org</a></p> <p>E-mail your resume, coverletter and any other materials to <a href="mailto:jobs@edx.org">jobs@edx.org</a></p>
<h2>Our Location</h2> <h2>Our Location</h2>
......
...@@ -250,3 +250,24 @@ task :autodeploy_properties do ...@@ -250,3 +250,24 @@ task :autodeploy_properties do
file.puts("UPSTREAM_REVISION=#{COMMIT}") file.puts("UPSTREAM_REVISION=#{COMMIT}")
end end
end end
desc "Invoke sphinx 'make build' to generate docs."
task :builddocs do
Dir.chdir('docs') do
sh('make html')
end
end
desc "Show doc in browser (mac only for now) TODO add linux support"
task :showdocs do
Dir.chdir('docs/build/html') do
sh('open index.html')
end
end
desc "Build docs and show them in browser"
task :doc => :builddocs do
Dir.chdir('docs/build/html') do
sh('open index.html')
end
end
\ No newline at end of file
...@@ -50,5 +50,7 @@ pygraphviz ...@@ -50,5 +50,7 @@ pygraphviz
-r repo-requirements.txt -r repo-requirements.txt
pil pil
nltk nltk
django-debug-toolbar-mongo
dogstatsd-python dogstatsd-python
MySQL-python MySQL-python
sphinx
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