Commit 9cf2ee45 by Tim Krones

Implement submission logic.

parent af8f576f
......@@ -4,24 +4,50 @@ function MentoringWithStepsBlock(runtime, element) {
function(c) { return c.element.className.indexOf('pb-mentoring-step') > -1; }
);
var active_child = -1;
var submitDOM, nextDOM;
var checkmark, submitDOM, nextDOM;
function isLastChild() {
return (active_child === steps.length-1);
}
function handleResults(response) {
if (response.completed === 'correct') {
checkmark.addClass('checkmark-correct icon-ok fa-check');
} else if (response.completed === 'partial') {
checkmark.addClass('checkmark-partially-correct icon-ok fa-check');
} else {
checkmark.addClass('checkmark-incorrect icon-exclamation fa-exclamation');
}
submitDOM.attr('disabled', 'disabled');
nextDOM.removeAttr("disabled");
if (nextDOM.is(':visible')) { nextDOM.focus(); }
}
function submit() {
// We do not handle submissions at this level, so just forward to "submit" method of current step
var child = steps[active_child];
child['submit'](handleResults);
}
function hideAllSteps() {
for (var i=0; i < steps.length; i++) {
$(steps[i].element).hide();
}
}
function displayNextChild() {
function cleanAll() {
checkmark.removeClass('checkmark-correct icon-ok fa-check');
checkmark.removeClass('checkmark-partially-correct icon-ok fa-check');
checkmark.removeClass('checkmark-incorrect icon-exclamation fa-exclamation');
hideAllSteps();
}
function displayNextChild() {
cleanAll();
findNextChild();
if (isLastChild()) {
nextDOM.attr('disabled', 'disabled');
}
nextDOM.attr('disabled', 'disabled');
validateXBlock();
}
......@@ -33,7 +59,12 @@ function MentoringWithStepsBlock(runtime, element) {
}
function onChange() {
validateXBlock();
// We do not allow users to modify answers belonging to a step after submitting them:
// Once an answer has been submitted (next button is enabled),
// start ignoring changes to the answer.
if (nextDOM.attr('disabled')) {
validateXBlock();
}
}
function validateXBlock() {
......@@ -47,6 +78,9 @@ function MentoringWithStepsBlock(runtime, element) {
} else {
submitDOM.removeAttr('disabled');
}
if (isLastChild()) {
nextDOM.hide();
}
}
function initSteps(options) {
......@@ -57,12 +91,14 @@ function MentoringWithStepsBlock(runtime, element) {
}
function initXBlockView() {
checkmark = $('.assessment-checkmark', element);
submitDOM = $(element).find('.submit .input-main');
submitDOM.bind('click', submit);
submitDOM.show();
nextDOM = $(element).find('.submit .input-next');
nextDOM.bind('click', displayNextChild);
nextDOM.removeAttr('disabled');
nextDOM.show();
var options = {
......
function MentoringStepBlock(runtime, element) {
var children = runtime.children(element);
var submitXHR;
function callIfExists(obj, fn) {
if (typeof obj !== 'undefined' && typeof obj[fn] == 'function') {
......@@ -31,6 +32,25 @@ function MentoringStepBlock(runtime, element) {
}
}
return is_valid;
},
submit: function(result_handler) {
var handler_name = 'submit';
var data = {};
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child && child.name !== undefined && typeof(child[handler_name]) !== "undefined") {
data[child.name.toString()] = child[handler_name]();
}
}
var handlerUrl = runtime.handlerUrl(element, handler_name);
if (submitXHR) {
submitXHR.abort();
}
submitXHR = $.post(handlerUrl, JSON.stringify(data))
.success(function(response) {
result_handler(response);
});
}
};
......
......@@ -18,12 +18,13 @@
# "AGPLv3". If not, see <http://www.gnu.org/licenses/>.
#
import logging
from lazy.lazy import lazy
from xblock.core import XBlock
from xblock.fields import String, Boolean, Scope
from xblock.fields import String, List, Scope
from xblock.fragment import Fragment
from xblockutils.helpers import child_isinstance
from xblockutils.resources import ResourceLoader
from xblockutils.studio_editable import (
NestedXBlockSpec, StudioEditableXBlockMixin, StudioContainerWithNestedXBlocksMixin, XBlockWithPreviewMixin
......@@ -31,11 +32,12 @@ from xblockutils.studio_editable import (
from problem_builder.answer import AnswerBlock, AnswerRecapBlock
from problem_builder.mcq import MCQBlock, RatingBlock
from problem_builder.mixins import EnumerableChildMixin
from problem_builder.mixins import EnumerableChildMixin, StepParentMixin
from problem_builder.mrq import MRQBlock
from problem_builder.table import MentoringTableBlock
log = logging.getLogger(__name__)
loader = ResourceLoader(__name__)
......@@ -64,7 +66,7 @@ class HtmlBlockShim(object):
@XBlock.needs('i18n')
class MentoringStepBlock(
StudioEditableXBlockMixin, StudioContainerWithNestedXBlocksMixin, XBlockWithPreviewMixin,
EnumerableChildMixin, XBlock
EnumerableChildMixin, StepParentMixin, XBlock
):
"""
An XBlock for a step.
......@@ -80,6 +82,11 @@ class MentoringStepBlock(
default="",
scope=Scope.content
)
student_results = List(
# Store results of student choices.
default=[],
scope=Scope.user_state
)
editable_fields = ('display_name', 'show_title',)
......@@ -104,13 +111,38 @@ class MentoringStepBlock(
AnswerRecapBlock, MentoringTableBlock,
]
@property
def steps(self):
""" Get the usage_ids of all of this XBlock's children that are "Questions" """
from mixins import QuestionMixin
return [
_normalize_id(child_id) for child_id in self.children if child_isinstance(self, child_id, QuestionMixin)
]
@XBlock.json_handler
def submit(self, submissions, suffix=''):
log.info(u'Received submissions: {}'.format(submissions))
# Submit child blocks (questions) and gather results
submit_results = []
for child in self.get_steps():
if child.name and child.name in submissions:
submission = submissions[child.name]
child_result = child.submit(submission)
submit_results.append([child.name, child_result])
child.save() # FIXME: Is this necessary? Child blocks also save themselves ...
# Update results stored for this step
while self.student_results:
self.student_results.pop()
for result in submit_results:
self.student_results.append(result)
# Compute "answer status" for this step
if all(result[1]['status'] == 'correct' for result in submit_results):
completed = 'correct'
elif all(result[1]['status'] == 'incorrect' for result in submit_results):
completed = 'incorrect'
else:
completed = 'partial'
return {
'message': 'Success!',
'completed': completed,
'results': submit_results,
}
def author_edit_view(self, context):
"""
......
......@@ -10,6 +10,7 @@
<div class="assessment-question-block">
{{child_content|safe}}
<div class="submit">
<span class="assessment-checkmark fa icon-2x"></span>
<input type="button" class="input-main" value="Submit" disabled="disabled" />
<input type="button" class="input-next" value="Next Step" disabled="disabled" />
</div>
......
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