Commit 3fdf8e3d by Xavier Antoviaque

Add JS submission of answers, marking step as completed when non-empty

parent 175599d5
......@@ -5,8 +5,9 @@
import logging
from xblock.core import XBlock
from xblock.fields import Any, Scope
from xblock.fragment import Fragment
from xblock.problem import TextInputBlock
# Globals ###########################################################
......@@ -16,14 +17,39 @@ log = logging.getLogger(__name__)
# Classes ###########################################################
class AnswerBlock(TextInputBlock):
class AnswerBlock(XBlock):
"""
A field where the student enters an answer
Must be included as a child of a mentoring block. Answers are persisted as django model instances
to make them searchable and referenceable across xblocks.
"""
student_input = Any(help="Last input submitted by the student", default="", scope=Scope.user_state)
def mentoring_view(self, context):
# TODO: Not implemented
return Fragment(u'<textarea cols="100" rows="10"></textarea>')
def student_view(self, context=None): # pylint: disable=W0613
"""Returns default student view."""
return Fragment(u"<p>I can only appear inside problems.</p>")
def mentoring_view(self, context=None):
html = u'<textarea cols="100" rows="10" name="input">{}</textarea>'.format(self.student_input)
fragment = Fragment(html)
fragment.add_javascript("""
function AnswerBlock(runtime, element) {
return {
submit: function() {
return $(element).find(':input').serializeArray();
},
handleSubmit: function(result) {
$(element).find('.message').text((result || {}).error || '');
}
}
}
""")
fragment.initialize_js('AnswerBlock')
return fragment
def submit(self, submission):
self.student_input = submission[0]['value']
log.info(u'Answer submitted for`{}`: "{}"'.format(self.name, self.student_input))
return self.student_input
......@@ -6,7 +6,7 @@
import logging
from xblock.core import XBlock
from xblock.fields import Integer, Scope, String
from xblock.fields import Boolean, Scope, String
from xblock.fragment import Fragment
from .utils import load_resource, render_template
......@@ -31,7 +31,8 @@ class MentoringBlock(XBlock):
"""
prompt = String(help="Initial text displayed with the text input", default='Your answer?', scope=Scope.content)
completed = Integer(help="How many times the student has completed this", default=0, scope=Scope.user_state)
attempted = Boolean(help="Has the student attempted this mentoring step?", default=False, scope=Scope.user_state)
completed = Boolean(help="Has the student completed this mentoring step?", default=False, scope=Scope.user_state)
has_children = True
def get_children_fragment(self, context):
......@@ -64,6 +65,32 @@ class MentoringBlock(XBlock):
return fragment
@XBlock.json_handler
def submit(self, submissions, suffix=''):
log.info(u'Received submissions: {}'.format(submissions))
self.attempted = True
child_map = {}
for child_id in self.children: # pylint: disable=E1101
child = self.runtime.get_block(child_id)
if child.name:
child_map[child.name] = child
submit_results = {}
completed = True
for input_name, submission in submissions.items():
child = child_map[input_name]
submit_results[input_name] = child.submit(submission)
child.save()
completed = completed and submit_results[input_name]
self.completed = bool(completed)
return {
'submitResults': submit_results,
'completed': self.completed,
}
def studio_view(self, context):
return Fragment(u'Studio view body')
......
<div class="mentoring">
{% for name, c in named_children %}
{{c.body_html|safe}}
{% endfor %}
{% for name, c in named_children %}
{{c.body_html|safe}}
{% endfor %}
<input type='button' value='submit' class='submit'></input>
{% if self.completed %}
completed!
{% else %}
NOT completed
{% endif %}
</div>
<input type='button' value='check' class='check'></input>
function MentoringBlock(runtime, element) {
console.log('Mentoring JS initialized');
function callIfExists(obj, fn) {
if (typeof obj[fn] == 'function') {
return obj[fn].apply(obj, Array.prototype.slice.call(arguments, 2));
} else {
return undefined;
}
}
function handleSubmitResults(results) {
$.each(results.submitResults || {}, function(input, result) {
callIfExists(runtime.childMap(element, input), 'handleSubmit', result);
});
}
$(element).find('.submit').bind('click', function() {
var data = {};
var children = runtime.children(element);
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.name !== undefined) {
data[child.name] = callIfExists(child, 'submit');
}
}
var handlerUrl = runtime.handlerUrl(element, 'submit')
$.post(handlerUrl, JSON.stringify(data)).success(handleSubmitResults);
});
}
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