Merge remote-tracking branch 'origin/master' into MITx/feature/bridger/fast_course_grading

Conflicts:
	lms/djangoapps/courseware/module_render.py
	lms/djangoapps/courseware/views.py
This commit is contained in:
Bridger Maxwell
2012-08-06 16:49:05 -04:00
32 changed files with 847 additions and 234 deletions

View File

@@ -17,6 +17,7 @@ from xmodule.exceptions import NotFoundError
from progress import Progress
from capa.capa_problem import LoncapaProblem
from capa.responsetypes import StudentInputError
from capa.util import convert_files_to_filenames
log = logging.getLogger("mitx.courseware")
@@ -425,10 +426,9 @@ class CapaModule(XModule):
event_info = dict()
event_info['state'] = self.lcp.get_state()
event_info['problem_id'] = self.location.url()
answers = self.make_dict_of_responses(get)
event_info['answers'] = answers
event_info['answers'] = convert_files_to_filenames(answers)
# Too late. Cannot submit
if self.closed():
@@ -436,8 +436,7 @@ class CapaModule(XModule):
self.system.track_function('save_problem_check_fail', event_info)
raise NotFoundError('Problem is closed')
# Problem submitted. Student should reset before checking
# again.
# Problem submitted. Student should reset before checking again
if self.lcp.done and self.rerandomize == "always":
event_info['failure'] = 'unreset'
self.system.track_function('save_problem_check_fail', event_info)

View File

@@ -94,7 +94,15 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor):
msg = "Couldn't parse html in {0}.".format(filepath)
log.warning(msg)
system.error_tracker("Warning: " + msg)
return {'data' : html}
definition = {'data' : html}
# TODO (ichuang): remove this after migration
# for Fall 2012 LMS migration: keep filename (and unmangled filename)
definition['filename'] = [ filepath, filename ]
return definition
except (ResourceNotFoundError) as err:
msg = 'Unable to load file contents at path {0}: {1} '.format(
filepath, err)

View File

@@ -13,7 +13,8 @@ class @Problem
MathJax.Hub.Queue ["Typeset", MathJax.Hub]
window.update_schematics()
@$('section.action input:button').click @refreshAnswers
@$('section.action input.check').click @check
@$('section.action input.check').click @check_fd
#@$('section.action input.check').click @check
@$('section.action input.reset').click @reset
@$('section.action input.show').click @show
@$('section.action input.save').click @save
@@ -45,6 +46,51 @@ class @Problem
$('head')[0].appendChild(s[0])
$(placeholder).remove()
###
# 'check_fd' uses FormData to allow file submissions in the 'problem_check' dispatch,
# in addition to simple querystring-based answers
#
# NOTE: The dispatch 'problem_check' is being singled out for the use of FormData;
# maybe preferable to consolidate all dispatches to use FormData
###
check_fd: =>
Logger.log 'problem_check', @answers
# If there are no file inputs in the problem, we can fall back on @check
if $('input:file').length == 0
@check()
return
if not window.FormData
alert "Sorry, your browser does not support file uploads. Your submit request could not be fulfilled. If you can, please use Chrome or Safari which have been verified to support file uploads."
return
fd = new FormData()
@$("[id^=input_#{@element_id.replace(/problem_/, '')}_]").each (index, element) ->
if element.type is 'file'
if element.files[0] instanceof File
fd.append(element.id, element.files[0])
else
fd.append(element.id, '')
else
fd.append(element.id, element.value)
settings =
type: "POST"
data: fd
processData: false
contentType: false
success: (response) =>
switch response.success
when 'incorrect', 'correct'
@render(response.contents)
@updateProgress response
else
alert(response.success)
$.ajaxWithPrefix("#{@url}/problem_check", settings)
check: =>
Logger.log 'problem_check', @answers
$.postWithPrefix "#{@url}/problem_check", @answers, (response) =>

View File

@@ -146,19 +146,30 @@ class XMLModuleStore(ModuleStoreBase):
os.path.exists(self.data_dir / d / "course.xml")]
for course_dir in course_dirs:
try:
# Special-case code here, since we don't have a location for the
# course before it loads.
# So, make a tracker to track load-time errors, then put in the right
# place after the course loads and we have its location
errorlog = make_error_tracker()
course_descriptor = self.load_course(course_dir, errorlog.tracker)
self.courses[course_dir] = course_descriptor
self._location_errors[course_descriptor.location] = errorlog
except:
msg = "Failed to load course '%s'" % course_dir
log.exception(msg)
self.try_load_course(course_dir)
def try_load_course(self,course_dir):
'''
Load a course, keeping track of errors as we go along.
'''
try:
# Special-case code here, since we don't have a location for the
# course before it loads.
# So, make a tracker to track load-time errors, then put in the right
# place after the course loads and we have its location
errorlog = make_error_tracker()
course_descriptor = self.load_course(course_dir, errorlog.tracker)
self.courses[course_dir] = course_descriptor
self._location_errors[course_descriptor.location] = errorlog
except:
msg = "Failed to load course '%s'" % course_dir
log.exception(msg)
def __unicode__(self):
'''
String representation - for debugging
'''
return '<XMLModuleStore>data_dir=%s, %d courses, %d modules' % (self.data_dir,len(self.courses),len(self.modules))
def load_course(self, course_dir, tracker):
"""

View File

@@ -204,6 +204,8 @@ class XModule(HTMLSnippet):
'''
return self.metadata.get('display_name',
self.url_name.replace('_', ' '))
def __unicode__(self):
return '<x_module(name=%s, category=%s, id=%s)>' % (self.name, self.category, self.id)
def get_children(self):
'''

View File

@@ -41,6 +41,7 @@ class XmlDescriptor(XModuleDescriptor):
# to definition_from_xml, and from the xml returned by definition_to_xml
metadata_attributes = ('format', 'graceperiod', 'showanswer', 'rerandomize',
'start', 'due', 'graded', 'display_name', 'url_name', 'hide_from_toc',
'ispublic', # if True, then course is listed for all users; see
# VS[compat] Remove once unused.
'name', 'slug')
@@ -109,6 +110,7 @@ class XmlDescriptor(XModuleDescriptor):
filename = xml_object.get('filename')
if filename is None:
definition_xml = copy.deepcopy(xml_object)
filepath = ''
else:
filepath = cls._format_filepath(xml_object.tag, filename)
@@ -136,7 +138,13 @@ class XmlDescriptor(XModuleDescriptor):
raise Exception, msg, sys.exc_info()[2]
cls.clean_metadata_from_xml(definition_xml)
return cls.definition_from_xml(definition_xml, system)
definition = cls.definition_from_xml(definition_xml, system)
# TODO (ichuang): remove this after migration
# for Fall 2012 LMS migration: keep filename (and unmangled filename)
definition['filename'] = [ filepath, filename ]
return definition
@classmethod