Commit e352226d by Victor Shnayder

Merge remote-tracking branch 'origin/master' into 700x-sandbox

parents d48efa85 f80181be
import json
import shutil
from django.test.client import Client
from override_settings import override_settings
from django.test.utils import override_settings
from django.conf import settings
from django.core.urlresolvers import reverse
from path import path
......@@ -10,6 +10,7 @@ import json
from fs.osfs import OSFS
import copy
from mock import Mock
from json import dumps, loads
from student.models import Registration
from django.contrib.auth.models import User
......@@ -26,10 +27,12 @@ from xmodule.contentstore.django import contentstore
from xmodule.templates import update_templates
from xmodule.modulestore.xml_exporter import export_to_xml
from xmodule.modulestore.xml_importer import import_from_xml
from xmodule.templates import update_templates
from xmodule.capa_module import CapaDescriptor
from xmodule.course_module import CourseDescriptor
from xmodule.seq_module import SequenceDescriptor
from xmodule.modulestore.exceptions import ItemNotFoundError
TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE)
TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data')
......@@ -207,6 +210,15 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
# check for custom_tags
self.verify_content_existence(ms, root_dir, location, 'custom_tags', 'custom_tag_template')
# check for graiding_policy.json
fs = OSFS(root_dir / 'test_export/policies/6.002_Spring_2012')
self.assertTrue(fs.exists('grading_policy.json'))
# compare what's on disk compared to what we have in our course
with fs.open('grading_policy.json','r') as grading_policy:
on_disk = loads(grading_policy.read())
course = ms.get_item(location)
self.assertEqual(on_disk, course.definition['data']['grading_policy'])
# remove old course
delete_course(ms, cs, location)
......@@ -399,3 +411,32 @@ class ContentStoreTest(ModuleStoreTestCase):
self.assertIn('markdown', context, "markdown is missing from context")
self.assertIn('markdown', problem.metadata, "markdown is missing from metadata")
self.assertNotIn('markdown', problem.editable_metadata_fields, "Markdown slipped into the editable metadata fields")
class TemplateTestCase(ModuleStoreTestCase):
def test_template_cleanup(self):
ms = modulestore('direct')
# insert a bogus template in the store
bogus_template_location = Location('i4x', 'edx', 'templates', 'html', 'bogus')
source_template_location = Location('i4x', 'edx', 'templates', 'html', 'Empty')
ms.clone_item(source_template_location, bogus_template_location)
verify_create = ms.get_item(bogus_template_location)
self.assertIsNotNone(verify_create)
# now run cleanup
update_templates()
# now try to find dangling template, it should not be in DB any longer
asserted = False
try:
verify_create = ms.get_item(bogus_template_location)
except ItemNotFoundError:
asserted = True
self.assertTrue(asserted)
......@@ -249,7 +249,7 @@ class CourseGradingTest(CourseTestCase):
altered_grader = CourseGradingModel.update_from_json(test_grader.__dict__)
self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "cutoff add D")
test_grader.grace_period = {'hours' : '4'}
test_grader.grace_period = {'hours' : 4, 'minutes' : 5, 'seconds': 0}
altered_grader = CourseGradingModel.update_from_json(test_grader.__dict__)
self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "4 hour grace period")
......
import json
import shutil
from django.test.client import Client
from override_settings import override_settings
from django.conf import settings
from django.core.urlresolvers import reverse
from path import path
......@@ -86,7 +85,6 @@ class ContentStoreTestCase(ModuleStoreTestCase):
# Now make sure that the user is now actually activated
self.assertTrue(user(email).is_active)
class AuthTestCase(ContentStoreTestCase):
"""Check that various permissions-related things work"""
......
......@@ -2,7 +2,6 @@ import json
import copy
from time import time
from django.test import TestCase
from override_settings import override_settings
from django.conf import settings
from student.models import Registration
......
......@@ -155,7 +155,8 @@ class CourseGradingModel(object):
if 'grace_period' in graceperiodjson:
graceperiodjson = graceperiodjson['grace_period']
grace_rep = " ".join(["%s %s" % (value, key) for (key, value) in graceperiodjson.iteritems()])
# lms requires these to be in a fixed order
grace_rep = "{0[hours]:d} hours {0[minutes]:d} minutes {0[seconds]:d} seconds".format(graceperiodjson)
descriptor = get_modulestore(course_location).get_item(course_location)
descriptor.metadata['graceperiod'] = grace_rep
......@@ -234,10 +235,10 @@ class CourseGradingModel(object):
@staticmethod
def convert_set_grace_period(descriptor):
# 5 hours 59 minutes 59 seconds => converted to iso format
# 5 hours 59 minutes 59 seconds => { hours: 5, minutes : 59, seconds : 59}
rawgrace = descriptor.metadata.get('graceperiod', None)
if rawgrace:
parsedgrace = {str(key): val for (val, key) in re.findall('\s*(\d+)\s*(\w+)', rawgrace)}
parsedgrace = {str(key): int(val) for (val, key) in re.findall('\s*(\d+)\s*(\w+)', rawgrace)}
return parsedgrace
else: return None
......
......@@ -58,6 +58,9 @@ $(document).ready(function() {
drop: onSectionReordered,
greedy: true
});
// stop clicks on drag bars from doing their thing w/o stopping drag
$('.drag-handle').click(function(e) {e.preventDefault(); });
});
......@@ -202,13 +205,17 @@ function _handleReorder(event, ui, parentIdField, childrenSelector) {
children = _.without(children, ui.draggable.data('id'));
}
// add to this parent (figure out where)
for (var i = 0; i < _els.length; i++) {
if (!ui.draggable.is(_els[i]) && ui.offset.top < $(_els[i]).offset().top) {
for (var i = 0, bump = 0; i < _els.length; i++) {
if (ui.draggable.is(_els[i])) {
bump = -1; // bump indicates that the draggable was passed in the dom but not children's list b/c
// it's not in that list
}
else if (ui.offset.top < $(_els[i]).offset().top) {
// insert at i in children and _els
ui.draggable.insertBefore($(_els[i]));
// TODO figure out correct way to have it remove the style: top:n; setting (and similar line below)
ui.draggable.attr("style", "position:relative;");
children.splice(i, 0, ui.draggable.data('id'));
children.splice(i + bump, 0, ui.draggable.data('id'));
break;
}
}
......
......@@ -227,7 +227,7 @@ CMS.Views.Settings.Details = CMS.Views.ValidatingView.extend({
time = 0;
}
var newVal = new Date(date.getTime() + time * 1000);
if (cacheModel.get(fieldName).getTime() !== newVal.getTime()) {
if (!cacheModel.has(fieldName) || cacheModel.get(fieldName).getTime() !== newVal.getTime()) {
cacheModel.save(fieldName, newVal, { error: CMS.ServerError});
}
}
......
......@@ -2,7 +2,7 @@ import django.test
from django.contrib.auth.models import User
from django.conf import settings
from override_settings import override_settings
from django.test.utils import override_settings
from course_groups.models import CourseUserGroup
from course_groups.cohorts import (get_cohort, get_course_cohorts,
......
from django.conf import settings
from django.test import TestCase
import os
from override_settings import override_settings
from django.test.utils import override_settings
from tempfile import NamedTemporaryFile
from status import get_site_status_msg
......
......@@ -18,10 +18,13 @@ def jsdate_to_time(field):
"""
if field is None:
return field
elif isinstance(field, basestring): # iso format but ignores time zone assuming it's Z
d = datetime.datetime(*map(int, re.split('[^\d]', field)[:6])) # stop after seconds. Debatable
elif isinstance(field, basestring):
# ISO format but ignores time zone assuming it's Z.
d = datetime.datetime(*map(int, re.split('[^\d]', field)[:6])) # stop after seconds. Debatable
return d.utctimetuple()
elif isinstance(field, int) or isinstance(field, float):
elif isinstance(field, (int, long, float)):
return time.gmtime(field / 1000)
elif isinstance(field, time.struct_time):
return field
else:
raise ValueError("Couldn't convert %r to time" % field)
......@@ -633,9 +633,13 @@ class MultipleChoiceResponse(LoncapaResponse):
# define correct choices (after calling secondary setup)
xml = self.xml
cxml = xml.xpath('//*[@id=$id]//choice', id=xml.get('id'))
self.correct_choices = [contextualize_text(choice.get('name'),
self.context) for choice in cxml if
contextualize_text(choice.get('correct'), self.context) == "true"]
# contextualize correct attribute and then select ones for which
# correct = "true"
self.correct_choices = [
contextualize_text(choice.get('name'), self.context)
for choice in cxml
if contextualize_text(choice.get('correct'), self.context) == "true"]
def mc_setup_response(self):
'''
......
......@@ -50,6 +50,7 @@
},
smartIndent: false
});
$("#textbox_${id}").find('.CodeMirror-scroll').height(${int(13.5*eval(rows))});
});
</script>
</section>
......@@ -446,7 +446,7 @@ class CourseDescriptor(SequenceDescriptor):
# utility function to get datetime objects for dates used to
# compute the is_new flag and the sorting_score
def to_datetime(timestamp):
return datetime.fromtimestamp(time.mktime(timestamp))
return datetime(*timestamp[:6])
def get_date(field):
timetuple = self._try_parse_time(field)
......
......@@ -2,6 +2,7 @@ import logging
from xmodule.modulestore import Location
from xmodule.modulestore.django import modulestore
from fs.osfs import OSFS
from json import dumps
def export_to_xml(modulestore, contentstore, course_location, root_dir, course_dir):
......@@ -27,6 +28,12 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d
# export the course updates
export_extra_content(export_fs, modulestore, course_location, 'course_info', 'info', '.html')
# export the grading policy
policies_dir = export_fs.makeopendir('policies')
course_run_policy_dir = policies_dir.makeopendir(course.location.name)
with course_run_policy_dir.open('grading_policy.json', 'w') as grading_policy:
grading_policy.write(dumps(course.definition['data']['grading_policy']))
def export_extra_content(export_fs, modulestore, course_location, category_type, dirname, file_suffix=''):
query_loc = Location('i4x', course_location.org, course_location.course, category_type, None)
......
......@@ -56,6 +56,10 @@ def update_templates():
available from the installed plugins
"""
# cdodge: build up a list of all existing templates. This will be used to determine which
# templates have been removed from disk - and thus we need to remove from the DB
templates_to_delete = modulestore('direct').get_items(['i4x', 'edx', 'templates', None, None, None])
for category, templates in all_templates().items():
for template in templates:
if 'display_name' not in template.metadata:
......@@ -85,3 +89,12 @@ def update_templates():
modulestore('direct').update_item(template_location, template.data)
modulestore('direct').update_children(template_location, template.children)
modulestore('direct').update_metadata(template_location, template.metadata)
# remove template from list of templates to delete
templates_to_delete = [t for t in templates_to_delete if t.location != template_location]
# now remove all templates which appear to have removed from disk
if len(templates_to_delete) > 0:
logging.debug('deleting dangling templates = {0}'.format(templates_to_delete))
for template in templates_to_delete:
modulestore('direct').delete_item(template.location)
......@@ -86,8 +86,8 @@ class TimeLimitModule(XModule):
modified_duration = self._get_accommodated_duration(duration)
self.ending_at = self.beginning_at + modified_duration
def get_end_time_in_ms(self):
return int(self.ending_at * 1000)
def get_remaining_time_in_ms(self):
return int((self.ending_at - time()) * 1000)
def get_instance_state(self):
state = {}
......
......@@ -50,7 +50,7 @@ if Backbone?
convertMath: ->
element = @$(".post-body")
element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.html()
element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.text()
MathJax.Hub.Queue ["Typeset", MathJax.Hub, element[0]]
renderResponses: ->
......
......@@ -47,7 +47,7 @@ if Backbone?
convertMath: ->
element = @$(".post-body")
element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.html()
element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.text()
MathJax.Hub.Queue ["Typeset", MathJax.Hub, element[0]]
toggleVote: (event) ->
......
......@@ -26,7 +26,7 @@ if Backbone?
convertMath: ->
body = @$el.find(".response-body")
body.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight body.html()
body.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight body.text()
MathJax.Hub.Queue ["Typeset", MathJax.Hub, body[0]]
markAsStaff: ->
......
......@@ -30,7 +30,7 @@ if Backbone?
convertMath: ->
element = @$(".response-body")
element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.html()
element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.text()
MathJax.Hub.Queue ["Typeset", MathJax.Hub, element[0]]
markAsStaff: ->
......
from django.core.urlresolvers import reverse
from override_settings import override_settings
from django.test.utils import override_settings
import xmodule.modulestore.django
......
......@@ -11,7 +11,7 @@ from django.test import TestCase
from django.test.client import RequestFactory
from django.conf import settings
from django.core.urlresolvers import reverse
from override_settings import override_settings
from django.test.utils import override_settings
import xmodule.modulestore.django
from xmodule.modulestore.mongo import MongoModuleStore
......
......@@ -177,10 +177,10 @@ def check_for_active_timelimit_module(request, course_id, course):
raise Http404("No {0} metadata at this location: {1} ".format('time_expired_redirect_url', location))
time_expired_redirect_url = timelimit_descriptor.metadata.get('time_expired_redirect_url')
context['time_expired_redirect_url'] = time_expired_redirect_url
# Fetch the end time (in GMT) as stored in the module when it was started.
# This value should be UTC time as number of milliseconds since epoch.
end_date = timelimit_module.get_end_time_in_ms()
context['timer_expiration_datetime'] = end_date
# Fetch the remaining time relative to the end time as stored in the module when it was started.
# This value should be in milliseconds.
remaining_time = timelimit_module.get_remaining_time_in_ms()
context['timer_expiration_duration'] = remaining_time
if 'suppress_toplevel_navigation' in timelimit_descriptor.metadata:
context['suppress_toplevel_navigation'] = timelimit_descriptor.metadata['suppress_toplevel_navigation']
return_url = reverse('jump_to', kwargs={'course_id':course_id, 'location':location})
......@@ -191,7 +191,7 @@ def update_timelimit_module(user, course_id, student_module_cache, timelimit_des
'''
Updates the state of the provided timing module, starting it if it hasn't begun.
Returns dict with timer-related values to enable display of time remaining.
Returns 'timer_expiration_datetime' in dict if timer is still active, and not if timer has expired.
Returns 'timer_expiration_duration' in dict if timer is still active, and not if timer has expired.
'''
context = {}
# determine where to go when the exam ends:
......@@ -215,10 +215,9 @@ def update_timelimit_module(user, course_id, student_module_cache, timelimit_des
instance_module.save()
# the exam has been started, either because the student is returning to the
# exam page, or because they have just visited it. Fetch the end time (in GMT) as stored
# in the module when it was started.
# This value should be UTC time as number of milliseconds since epoch.
context['timer_expiration_datetime'] = timelimit_module.get_end_time_in_ms()
# exam page, or because they have just visited it. Fetch the remaining time relative to the
# end time as stored in the module when it was started.
context['timer_expiration_duration'] = timelimit_module.get_remaining_time_in_ms()
# also use the timed module to determine whether top-level navigation is visible:
if 'suppress_toplevel_navigation' in timelimit_descriptor.metadata:
context['suppress_toplevel_navigation'] = timelimit_descriptor.metadata['suppress_toplevel_navigation']
......@@ -325,7 +324,7 @@ def index(request, course_id, chapter=None, section=None,
if section_module.category == 'timelimit':
timer_context = update_timelimit_module(request.user, course_id, student_module_cache,
section_descriptor, section_module)
if 'timer_expiration_datetime' in timer_context:
if 'timer_expiration_duration' in timer_context:
context.update(timer_context)
else:
# if there is no expiration defined, then we know the timer has expired:
......
......@@ -6,7 +6,7 @@ from django.conf import settings
from mock import Mock
from override_settings import override_settings
from django.test.utils import override_settings
import xmodule.modulestore.django
......
......@@ -11,6 +11,8 @@ from django.http import HttpResponse
from django.utils import simplejson
from django_comment_client.models import Role
from django_comment_client.permissions import check_permissions_by_view
from xmodule.modulestore.exceptions import NoPathToItem
from mitxmako import middleware
import pystache_custom as pystache
......@@ -164,6 +166,7 @@ def initialize_discussion_info(course):
# get all discussion models within this course_id
all_modules = modulestore().get_items(['i4x', course.location.org, course.location.course, 'discussion', None], course_id=course_id)
path_to_locations = {}
for module in all_modules:
skip_module = False
for key in ('id', 'discussion_category', 'for'):
......@@ -171,6 +174,14 @@ def initialize_discussion_info(course):
log.warning("Required key '%s' not in discussion %s, leaving out of category map" % (key, module.location))
skip_module = True
# cdodge: pre-compute the path_to_location. Note this can throw an exception for any
# dangling discussion modules
try:
path_to_locations[module.location] = path_to_location(modulestore(), course.id, module.location)
except NoPathToItem:
log.warning("Could not compute path_to_location for {0}. Perhaps this is an orphaned discussion module?!? Skipping...".format(module.location))
skip_module = True
if skip_module:
continue
......@@ -235,6 +246,7 @@ def initialize_discussion_info(course):
_DISCUSSIONINFO[course.id]['id_map'] = discussion_id_map
_DISCUSSIONINFO[course.id]['category_map'] = category_map
_DISCUSSIONINFO[course.id]['timestamp'] = datetime.now()
_DISCUSSIONINFO[course.id]['path_to_location'] = path_to_locations
class JsonResponse(HttpResponse):
......@@ -390,11 +402,23 @@ def get_courseware_context(content, course):
if id in id_map:
location = id_map[id]["location"].url()
title = id_map[id]["title"]
(course_id, chapter, section, position) = path_to_location(modulestore(), course.id, location)
url = reverse('courseware_position', kwargs={"course_id": course_id,
"chapter": chapter,
"section": section,
"position": position})
# cdodge: did we pre-compute, if so, then let's use that rather than recomputing
if 'path_to_location' in _DISCUSSIONINFO[course.id] and location in _DISCUSSIONINFO[course.id]['path_to_location']:
(course_id, chapter, section, position) = _DISCUSSIONINFO[course.id]['path_to_location'][location]
else:
try:
(course_id, chapter, section, position) = path_to_location(modulestore(), course.id, location)
except NoPathToItem:
# Object is not in the graph any longer, let's just get path to the base of the course
# so that we can at least return something to the caller
(course_id, chapter, section, position) = path_to_location(modulestore(), course.id, course.location)
url = reverse('courseware_position', kwargs={"course_id":course_id,
"chapter":chapter,
"section":section,
"position":position})
content_info = {"courseware_url": url, "courseware_title": title}
return content_info
......
......@@ -15,7 +15,7 @@ import json
from nose import SkipTest
from mock import patch, Mock
from override_settings import override_settings
from django.test.utils import override_settings
# Need access to internal func to put users in the right group
from django.contrib.auth.models import Group
......
......@@ -22,7 +22,7 @@ from mitxmako.shortcuts import render_to_string
import logging
log = logging.getLogger(__name__)
from override_settings import override_settings
from django.test.utils import override_settings
from django.http import QueryDict
......
......@@ -200,7 +200,6 @@ COURSE_TITLE = "Circuits and Electronics"
### Dark code. Should be enabled in local settings for devel.
ENABLE_MULTICOURSE = False # set to False to disable multicourse display (see lib.util.views.mitxhome)
QUICKEDIT = False
WIKI_ENABLED = False
......
......@@ -34,7 +34,6 @@ EDX4EDX_ROOT = ENV_ROOT / "data/edx4edx"
DEBUG = True
ENABLE_MULTICOURSE = True # set to False to disable multicourse display (see lib.util.views.mitxhome)
QUICKEDIT = True
MAKO_TEMPLATES['course'] = [DATA_DIR, EDX4EDX_ROOT]
......
......@@ -6,7 +6,6 @@ COURSE_TITLE = "edx4edx: edX Author Course"
EDX4EDX_ROOT = ENV_ROOT / "data/edx4edx"
### Dark code. Should be enabled in local settings for devel.
QUICKEDIT = True
ENABLE_MULTICOURSE = True # set to False to disable multicourse display (see lib.util.views.mitxhome)
###
PIPELINE_CSS_COMPRESSOR = None
......
This is a library for edx4edx, allowing users to practice writing problems.
#!/usr/bin/python
from random import choice
import string
import traceback
from django.conf import settings
import capa.capa_problem as lcp
from dogfood.views import update_problem
def GenID(length=8, chars=string.letters + string.digits):
return ''.join([choice(chars) for i in range(length)])
randomid = GenID()
def check_problem_code(ans, the_lcp, correct_answers, false_answers):
"""
ans = student's answer
the_lcp = LoncapaProblem instance
returns dict {'ok':is_ok,'msg': message with iframe}
"""
pfn = "dog%s" % randomid
pfn += the_lcp.problem_id.replace('filename', '') # add problem ID to dogfood problem name
update_problem(pfn, ans, filestore=the_lcp.system.filestore)
msg = '<hr width="100%"/>'
msg += '<iframe src="%s/dogfood/filename%s" width="95%%" height="400" frameborder="1">No iframe support!</iframe>' % (settings.MITX_ROOT_URL, pfn)
msg += '<hr width="100%"/>'
endmsg = """<p><font size="-1" color="purple">Note: if the code text box disappears after clicking on "Check",
please type something in the box to make it refresh properly. This is a
bug with Chrome; it does not happen with Firefox. It is being fixed.
</font></p>"""
is_ok = True
if (not correct_answers) or (not false_answers):
ret = {'ok': is_ok,
'msg': msg + endmsg,
}
return ret
try:
# check correctness
fp = the_lcp.system.filestore.open('problems/%s.xml' % pfn)
test_lcp = lcp.LoncapaProblem(fp, '1', system=the_lcp.system)
if not (test_lcp.grade_answers(correct_answers).get_correctness('1_2_1') == 'correct'):
is_ok = False
if (test_lcp.grade_answers(false_answers).get_correctness('1_2_1') == 'correct'):
is_ok = False
except Exception, err:
is_ok = False
msg += "<p>Error: %s</p>" % str(err).replace('<', '&#60;')
msg += "<p><pre>%s</pre></p>" % traceback.format_exc().replace('<', '&#60;')
ret = {'ok': is_ok,
'msg': msg + endmsg,
}
return ret
......@@ -67,7 +67,7 @@ section.course-index {
}
.chapter {
width: 100%;
width: 100% !important;
@include box-sizing(border-box);
padding: 11px 14px;
@include linear-gradient(top, rgba(255, 255, 255, .6), rgba(255, 255, 255, 0));
......@@ -99,6 +99,8 @@ section.course-index {
@include border-radius(0);
margin: 0;
padding: 9px 0 9px 9px;
overflow: auto;
width: 100%;
li {
border-bottom: 0;
......
......@@ -60,14 +60,12 @@
});
</script>
% if timer_expiration_datetime:
% if timer_expiration_duration:
<script type="text/javascript">
var timer = {
timer_inst : null,
get_remaining_secs : function() {
// set the end time when the template is rendered.
// This value should be UTC time as number of milliseconds since epoch.
var endTime = new Date(${timer_expiration_datetime});
timer_inst : null,
end_time : null,
get_remaining_secs : function(endTime) {
var currentTime = new Date();
var remaining_secs = Math.floor((endTime - currentTime)/1000);
return remaining_secs;
......@@ -87,13 +85,16 @@
return remainingTimeString;
},
update_time : function(self) {
remaining_secs = self.get_remaining_secs();
remaining_secs = self.get_remaining_secs(self.end_time);
if (remaining_secs <= 0) {
self.end(self);
}
$('#exam_timer').text(self.get_time_string(remaining_secs));
},
start : function() { var that = this;
// set the end time when the template is rendered.
// This value should be UTC time as number of milliseconds since epoch.
this.end_time = new Date((new Date()).getTime() + ${timer_expiration_duration});
this.timer_inst = setInterval(function(){ that.update_time(that); }, 1000);
},
end : function(self) {
......@@ -109,7 +110,7 @@
</%block>
% if timer_expiration_datetime:
% if timer_expiration_duration:
<div class="timer-main">
<div id="timer_wrapper">
% if timer_navigation_return_url:
......
<%namespace name='static' file='static_content.html'/>
<!DOCTYPE html>
<html>
## -----------------------------------------------------------------------------
## Template for lib.dogfood.views.dj_capa_problem
##
## Used for viewing assesment problems in "dogfood" self-evaluation mode
## -----------------------------------------------------------------------------
<head>
<link rel="stylesheet" href="${static.url('css/vendor/jquery.treeview.css')}" type="text/css" media="all" />
## <link rel="stylesheet" href="${ settings.LIB_URL }jquery.treeview.css" type="text/css" media="all" />
## <link rel="stylesheet" href="/static/sass/application.css" type="text/css" media="all" / >
% if settings.MITX_FEATURES['USE_DJANGO_PIPELINE']:
## <%static:css group='application'/>
% endif
% if not settings.MITX_FEATURES['USE_DJANGO_PIPELINE']:
## <link rel="stylesheet" href="/static/sass/application.css" type="text/css" media="all" / >
% endif
<script type="text/javascript" src="${static.url('js/jquery.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/jquery-ui.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/swfobject/swfobject.js')}"></script>
% if settings.MITX_FEATURES['USE_DJANGO_PIPELINE']:
<%static:js group='application'/>
% endif
% if not settings.MITX_FEATURES['USE_DJANGO_PIPELINE']:
% for jsfn in [ '/static/%s' % x.replace('.coffee','.js') for x in settings.PIPELINE_JS['application']['source_filenames'] ]:
<script type="text/javascript" src="${jsfn}"></script>
% endfor
% endif
## codemirror
<link rel="stylesheet" href="/static/css/codemirror.css" type="text/css" media="all" />
<script type="text/javascript" src="${ settings.LIB_URL }codemirror-compressed.js"></script>
## alternate codemirror
## <script type="text/javascript" src="/static/js/CodeMirror-2.25/lib/codemirror.js"></script>
## <script type="text/javascript" src="/static/js/CodeMirror-2.25/mode/xml/xml.js"></script>
## <script type="text/javascript" src="/static/js/CodeMirror-2.25/mode/python/python.js"></script>
## image input: for clicking on images (see imageinput.html)
<script type="text/javascript" src="/static/js/imageinput.js"></script>
<%include file="mathjax_include.html" />
</head>
<body class="courseware">
<!--[if lt IE 9]>
<script src="/static/js/html5shiv.js"></script>
<![endif]-->
<div class="courseware"></div>
## -----------------------------------------------------------------------------
## information
## <hr width="100%">
## <h2>Rendition of your problem code</h2>
## <hr width="100%">
## -----------------------------------------------------------------------------
## rendered problem display
<script>
${init_js}
</script>
<style type="text/css">
.problem-header {display:none;}
.staff {display:none;}
.correct { display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
vertical-align: baseline;
zoom: 1;
*display: inline;
*vertical-align: auto;
background: url("/static/images/correct-icon.png") center center no-repeat;
height: 20px;
position: relative;
top: 6px;
width: 25px; }
.incorrect{
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
vertical-align: baseline;
zoom: 1;
*display: inline;
*vertical-align: auto;
background: url("/static/images/incorrect-icon.png") center center no-repeat;
height: 20px;
width: 20px;
position: relative;
top: 6px; }
.unanswered {
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
vertical-align: baseline;
zoom: 1;
*display: inline;
*vertical-align: auto;
background: url("/static/images/unanswered-icon.png") center center no-repeat;
height: 14px;
position: relative;
top: 4px;
width: 14px; }
}
</style>
<meta name="path_prefix" content="${MITX_ROOT_URL}">
<section class="course-content">
<form>
${phtml}
</form>
</section>
<script type="text/javascript" src="${static.url('js/jquery.treeview.js')}"></script>
<script type="text/javascript" src="${static.url('js/jquery.leanModal.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/jquery.qtip.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/jquery.cookie.js')}"></script>
## <script type="text/javascript" src="${static.url('js/video_player.js')}"></script>
<script type="text/javascript" src="${static.url('js/schematic.js')}"></script>
<script type="text/javascript" src="${static.url('js/cktsim.js')}"></script>
## image input: for clicking on images (see imageinput.html)
<script type="text/javascript" src="/static/js/imageinput.js"></script>
<script type="text/javascript" >
var codemirror_set= {}; // associative array of codemirror objects
</script>
<%block name="js_extra"/>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html> <head>
<title>edX gitupdate</title>
</head>
<body>
<hr>
<h1>edX gitupdate</h1>
<hr>
<h2>Coursename: ${coursename}</h2>
% if msg:
${msg}
% else:
<p>
Do you REALLY want to overwrite all the course.xml + problems + html
files with version from the main git repository?
</p>
<form method="post">
<input type="submit" value="Do git update" name="gitupdate" />
## <input type="submit" value="Cancel" name="cancel" />
<input type="hidden" name="csrfmiddlewaretoken" value="${csrf}"/>
</form>
% endif
<p><a href="${MITX_ROOT_URL}/courseware/">Return to site</a></p>
</body> </html>
<%namespace name='static' file='static_content.html'/>
<!DOCTYPE html>
<html>
## -----------------------------------------------------------------------------
## Template for courseware.views.quickedit
##
## Used for quick-edit link present when viewing capa-format assesment problems.
## -----------------------------------------------------------------------------
<head>
<link rel="stylesheet" href="${static.url('css/vendor/jquery.treeview.css')}" type="text/css" media="all" />
## <link rel="stylesheet" href="${ settings.LIB_URL }jquery.treeview.css" type="text/css" media="all" />
## <link rel="stylesheet" href="/static/sass/application.css" type="text/css" media="all" / >
% if settings.MITX_FEATURES['USE_DJANGO_PIPELINE']:
<%static:css group='application'/>
% endif
% if not settings.MITX_FEATURES['USE_DJANGO_PIPELINE']:
## <link rel="stylesheet" href="/static/sass/application.css" type="text/css" media="all" / >
% endif
<script type="text/javascript" src="${static.url('js/jquery.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/jquery-ui.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/swfobject/swfobject.js')}"></script>
% if settings.MITX_FEATURES['USE_DJANGO_PIPELINE']:
<%static:js group='application'/>
% endif
% if not settings.MITX_FEATURES['USE_DJANGO_PIPELINE']:
% for jsfn in [ '/static/%s' % x.replace('.coffee','.js') for x in settings.PIPELINE_JS['application']['source_filenames'] ]:
<script type="text/javascript" src="${jsfn}"></script>
% endfor
% endif
## codemirror
<link rel="stylesheet" href="/static/css/codemirror.css" type="text/css" media="all" />
<script type="text/javascript" src="${ settings.LIB_URL }codemirror-compressed.js"></script>
## alternate codemirror
## <script type="text/javascript" src="/static/js/CodeMirror-2.25/lib/codemirror.js"></script>
## <script type="text/javascript" src="/static/js/CodeMirror-2.25/mode/xml/xml.js"></script>
## <script type="text/javascript" src="/static/js/CodeMirror-2.25/mode/python/python.js"></script>
## image input: for clicking on images (see imageinput.html)
<script type="text/javascript" src="/static/js/imageinput.js"></script>
## <script type="text/javascript">
## var codemirror_set = {}; // track all codemirror textareas, so they can be refreshed on page changes
## </script>
<!--[if lt IE 9]>
<script src="${static.url('js/html5shiv.js')}"></script>
<![endif]-->
<%block name="headextra"/>
<!-- This must appear after all mathjax-config blocks, so it is after the imports from the other templates.
It can't be run through static.url because MathJax uses crazy url introspection to do lazy loading of
MathJax extension libraries -->
<%include file="mathjax_include.html" />
</head>
<body class="courseware" style="text-align:left;" >
<style type="text/css">
.CodeMirror {border-style: solid;
border-width: 1px;}
.CodeMirror-scroll {
height: 500;
width: 100%
}
</style>
## -----------------------------------------------------------------------------
## information and i4x PSL code
<hr width="100%">
<h2>QuickEdit</h2>
<hr width="100%">
<ul>
<li>File = ${filename}</li>
<li>ID = ${id}</li>
</ul>
<form method="post">
<textarea rows="40" cols="160" name="quickedit_${id}" id="quickedit_${id}">${pxmls|h}</textarea>
<br/>
<input type="submit" value="Change Problem" name="qesubmit" />
<input type="submit" value="Revert to original" name="qesubmit" />
<input type="hidden" name="csrfmiddlewaretoken" value="${csrf}"/>
</form>
<span>${msg|n}</span>
## -----------------------------------------------------------------------------
## rendered problem display
<script>
// height: auto;
// overflow-y: hidden;
// overflow-x: auto;
$(function(){
var cm = CodeMirror.fromTextArea(document.getElementById("quickedit_${id}"),
{ 'mode': {name: "xml", alignCDATA: true},
lineNumbers: true
});
// $('.my-wymeditor').wymeditor();
});
</script>
<hr width="100%">
<script>
${init_js}
</script>
<style type="text/css">
.staff {display:none;}
.correct { display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
vertical-align: baseline;
zoom: 1;
*display: inline;
*vertical-align: auto;
background: url("/static/images/correct-icon.png") center center no-repeat;
height: 20px;
position: relative;
top: 6px;
width: 25px; }
.incorrect{
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
vertical-align: baseline;
zoom: 1;
*display: inline;
*vertical-align: auto;
background: url("/static/images/incorrect-icon.png") center center no-repeat;
height: 20px;
width: 20px;
position: relative;
top: 6px; }
}
</style>
<meta name="path_prefix" content="${MITX_ROOT_URL}">
<section class="course-content">
<div id="seq_content">
<form>
${phtml}
</form>
</div>
</section>
<script type="text/javascript" src="${static.url('js/jquery.treeview.js')}"></script>
<script type="text/javascript" src="${static.url('js/jquery.leanModal.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/jquery.qtip.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/jquery.cookie.js')}"></script>
## <script type="text/javascript" src="${static.url('js/video_player.js')}"></script>
<script type="text/javascript" src="${static.url('js/schematic.js')}"></script>
<script type="text/javascript" src="${static.url('js/cktsim.js')}"></script>
<script type="text/javascript" >
var codemirror_set= {}; // associative array of codemirror objects
</script>
<script type="text/javascript" src="${static.url('js/jquery.scrollTo-1.4.2-min.js')}"></script>
<%block name="js_extra"/>
</body>
</html>
......@@ -320,10 +320,6 @@ if settings.COURSEWARE_ENABLED:
'courseware.views.static_tab', name="static_tab"),
)
if settings.QUICKEDIT:
urlpatterns += (url(r'^quickedit/(?P<id>[^/]*)$', 'dogfood.views.quickedit'),)
urlpatterns += (url(r'^dogfood/(?P<id>[^/]*)$', 'dogfood.views.df_capa_problem'),)
if settings.ENABLE_JASMINE:
urlpatterns += (url(r'^_jasmine/', include('django_jasmine.urls')),)
......
......@@ -24,7 +24,6 @@ django_nose
nosexcover==1.0.7
rednose==0.3.3
GitPython==0.3.2.RC1
django-override-settings==1.2
mock==0.8.0
PyYAML==3.10
South==0.7.6
......
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