Commit 3fdf8e3d by Xavier Antoviaque

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

parent 175599d5
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
import logging import logging
from xblock.core import XBlock
from xblock.fields import Any, Scope
from xblock.fragment import Fragment from xblock.fragment import Fragment
from xblock.problem import TextInputBlock
# Globals ########################################################### # Globals ###########################################################
...@@ -16,14 +17,39 @@ log = logging.getLogger(__name__) ...@@ -16,14 +17,39 @@ log = logging.getLogger(__name__)
# Classes ########################################################### # Classes ###########################################################
class AnswerBlock(TextInputBlock): class AnswerBlock(XBlock):
""" """
A field where the student enters an answer 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 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. 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): def student_view(self, context=None): # pylint: disable=W0613
# TODO: Not implemented """Returns default student view."""
return Fragment(u'<textarea cols="100" rows="10"></textarea>') 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 @@ ...@@ -6,7 +6,7 @@
import logging import logging
from xblock.core import XBlock 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 xblock.fragment import Fragment
from .utils import load_resource, render_template from .utils import load_resource, render_template
...@@ -31,7 +31,8 @@ class MentoringBlock(XBlock): ...@@ -31,7 +31,8 @@ class MentoringBlock(XBlock):
""" """
prompt = String(help="Initial text displayed with the text input", default='Your answer?', scope=Scope.content) 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 has_children = True
def get_children_fragment(self, context): def get_children_fragment(self, context):
...@@ -64,6 +65,32 @@ class MentoringBlock(XBlock): ...@@ -64,6 +65,32 @@ class MentoringBlock(XBlock):
return fragment 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): def studio_view(self, context):
return Fragment(u'Studio view body') return Fragment(u'Studio view body')
......
<div class="mentoring"> <div class="mentoring">
{% for name, c in named_children %} {% for name, c in named_children %}
{{c.body_html|safe}} {{c.body_html|safe}}
{% endfor %} {% endfor %}
<input type='button' value='submit' class='submit'></input>
{% if self.completed %}
completed!
{% else %}
NOT completed
{% endif %}
</div> </div>
<input type='button' value='check' class='check'></input>
function MentoringBlock(runtime, element) { 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