Commit 36091697 by kimth

Student browser polls for queued submission result

parent 062eff12
...@@ -307,7 +307,18 @@ def filesubmission(element, value, status, render_template, msg=''): ...@@ -307,7 +307,18 @@ def filesubmission(element, value, status, render_template, msg=''):
Upload a single file (e.g. for programming assignments) Upload a single file (e.g. for programming assignments)
''' '''
eid = element.get('id') eid = element.get('id')
context = { 'id': eid, 'state': status, 'msg': msg, 'value': value, }
# Check if problem has been queued
queued = ''
queue_len = 0
if status == 'incomplete': # Flag indicating that the problem has been queued, 'msg' is length of queue
queued = 'true'
queue_len = msg
msg = 'Submitted to grader. (Queue length: %s)' % queue_len
context = { 'id': eid, 'state': status, 'msg': msg, 'value': value,
'queued': queued, 'queue_len': queue_len
}
html = render_template("filesubmission.html", context) html = render_template("filesubmission.html", context)
return etree.XML(html) return etree.XML(html)
...@@ -329,10 +340,18 @@ def textbox(element, value, status, render_template, msg=''): ...@@ -329,10 +340,18 @@ def textbox(element, value, status, render_template, msg=''):
hidden = element.get('hidden', '') # if specified, then textline is hidden and id is stored in div of name given by hidden hidden = element.get('hidden', '') # if specified, then textline is hidden and id is stored in div of name given by hidden
if not value: value = element.text # if no student input yet, then use the default input given by the problem if not value: value = element.text # if no student input yet, then use the default input given by the problem
# Check if problem has been queued
queued = ''
queue_len = 0
if status == 'incomplete': # Flag indicating that the problem has been queued, 'msg' is length of queue
queued = 'true'
queue_len = msg
msg = 'Submitted to grader. (Queue length: %s)' % queue_len
# For CodeMirror # For CodeMirror
mode = element.get('mode') or 'python' # mode, eg "python" or "xml" mode = element.get('mode','python')
linenumbers = element.get('linenumbers','true') # for CodeMirror linenumbers = element.get('linenumbers','true')
tabsize = element.get('tabsize','4') tabsize = element.get('tabsize','4')
tabsize = int(tabsize) tabsize = int(tabsize)
...@@ -340,6 +359,7 @@ def textbox(element, value, status, render_template, msg=''): ...@@ -340,6 +359,7 @@ def textbox(element, value, status, render_template, msg=''):
'mode': mode, 'linenumbers': linenumbers, 'mode': mode, 'linenumbers': linenumbers,
'rows': rows, 'cols': cols, 'rows': rows, 'cols': cols,
'hidden': hidden, 'tabsize': tabsize, 'hidden': hidden, 'tabsize': tabsize,
'queued': queued, 'queue_len': queue_len,
} }
html = render_template("textbox.html", context) html = render_template("textbox.html", context)
try: try:
......
...@@ -898,7 +898,7 @@ class CodeResponse(LoncapaResponse): ...@@ -898,7 +898,7 @@ class CodeResponse(LoncapaResponse):
'processor': self.code, 'processor': self.code,
} }
# Submit request # Submit request. When successful, 'msg' is the prior length of the queue
if is_file(submission): if is_file(submission):
contents.update({'edX_student_response': submission.name}) contents.update({'edX_student_response': submission.name})
(error, msg) = qinterface.send_to_queue(header=xheader, (error, msg) = qinterface.send_to_queue(header=xheader,
...@@ -914,8 +914,11 @@ class CodeResponse(LoncapaResponse): ...@@ -914,8 +914,11 @@ class CodeResponse(LoncapaResponse):
cmap.set(self.answer_id, queuekey=None, cmap.set(self.answer_id, queuekey=None,
msg='Unable to deliver your submission to grader. (Reason: %s.) Please try again later.' % msg) msg='Unable to deliver your submission to grader. (Reason: %s.) Please try again later.' % msg)
else: else:
# Non-null CorrectMap['queuekey'] indicates that the problem has been queued # Queueing mechanism flags:
cmap.set(self.answer_id, queuekey=queuekey, msg='Submitted to grader. (Queue length: %s)' % msg) # 1) Backend: Non-null CorrectMap['queuekey'] indicates that the problem has been queued
# 2) Frontend: correctness='incomplete' eventually trickles down through inputtypes.textbox
# and .filesubmission to inform the browser to poll the LMS
cmap.set(self.answer_id, queuekey=queuekey, correctness='incomplete', msg=msg)
return cmap return cmap
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
% elif state == 'incomplete': % elif state == 'incomplete':
<span class="incorrect" id="status_${id}"></span> <span class="incorrect" id="status_${id}"></span>
% endif % endif
% if queued:
<span class="xqueue" id="${id}" >${queue_len}</span>
% endif
<span class="debug">(${state})</span> <span class="debug">(${state})</span>
<br/> <br/>
<span class="message">${msg|n}</span> <span class="message">${msg|n}</span>
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
% if hidden: % if hidden:
<div style="display:none;" name="${hidden}" inputid="input_${id}" /> <div style="display:none;" name="${hidden}" inputid="input_${id}" />
% endif % endif
% if queued:
<span class="xqueue" id="${id}" >${queue_len}</span>
% endif
<br/> <br/>
<span class="debug">(${state})</span> <span class="debug">(${state})</span>
<br/> <br/>
......
...@@ -10,7 +10,8 @@ import time ...@@ -10,7 +10,8 @@ import time
# TODO: Collection of parameters to be hooked into rest of edX system # TODO: Collection of parameters to be hooked into rest of edX system
XQUEUE_LMS_AUTH = { 'username': 'LMS', XQUEUE_LMS_AUTH = { 'username': 'LMS',
'password': 'PaloAltoCA' } 'password': 'PaloAltoCA' }
XQUEUE_URL = 'http://xqueue.edx.org' #XQUEUE_URL = 'http://xqueue.edx.org'
XQUEUE_URL = 'http://ec2-50-17-47-60.compute-1.amazonaws.com'
log = logging.getLogger('mitx.' + __name__) log = logging.getLogger('mitx.' + __name__)
......
...@@ -4,6 +4,12 @@ class @Problem ...@@ -4,6 +4,12 @@ class @Problem
@id = @el.data('problem-id') @id = @el.data('problem-id')
@element_id = @el.attr('id') @element_id = @el.attr('id')
@url = @el.data('url') @url = @el.data('url')
# Destroy any existing polling threads on Problem change
if window.queuePollerID
window.clearTimeout(window.queuePollerID)
delete window.queuePollerID
@render() @render()
$: (selector) -> $: (selector) ->
...@@ -12,7 +18,10 @@ class @Problem ...@@ -12,7 +18,10 @@ class @Problem
bind: => bind: =>
MathJax.Hub.Queue ["Typeset", MathJax.Hub] MathJax.Hub.Queue ["Typeset", MathJax.Hub]
window.update_schematics() window.update_schematics()
@inputs = @$("[id^=input_#{@element_id.replace(/problem_/, '')}_]")
problem_prefix = @element_id.replace(/problem_/,'')
@inputs = @$("[id^=input_#{problem_prefix}_]")
@$('section.action input:button').click @refreshAnswers @$('section.action input:button').click @refreshAnswers
@$('section.action input.check').click @check_fd @$('section.action input.check').click @check_fd
#@$('section.action input.check').click @check #@$('section.action input.check').click @check
...@@ -26,15 +35,37 @@ class @Problem ...@@ -26,15 +35,37 @@ class @Problem
@el.attr progress: response.progress_status @el.attr progress: response.progress_status
@el.trigger('progressChanged') @el.trigger('progressChanged')
queueing: =>
@queued_items = @$(".xqueue")
if @queued_items.length > 0
if window.queuePollerID # Only one poller 'thread' per Problem
window.clearTimeout(window.queuePollerID)
window.queuePollerID = window.setTimeout(@poll, 100)
poll: =>
$.postWithPrefix "#{@url}/problem_get", (response) =>
@el.html(response.html)
@executeProblemScripts()
@bind()
@queued_items = @$(".xqueue")
if @queued_items.length == 0
delete window.queuePollerID
else
# TODO: Dynamically adjust timeout interval based on @queued_items.value
window.queuePollerID = window.setTimeout(@poll, 1000)
render: (content) -> render: (content) ->
if content if content
@el.html(content) @el.html(content)
@bind() @bind()
@queueing()
else else
$.postWithPrefix "#{@url}/problem_get", (response) => $.postWithPrefix "#{@url}/problem_get", (response) =>
@el.html(response.html) @el.html(response.html)
@executeProblemScripts() @executeProblemScripts()
@bind() @bind()
@queueing()
executeProblemScripts: -> executeProblemScripts: ->
@el.find(".script_placeholder").each (index, placeholder) -> @el.find(".script_placeholder").each (index, placeholder) ->
......
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