Commit 6d7d4fd8 by Stephen Sanchez

Ensuring the right many to many relationship is preserved for Assessment Feedback

parent 16c1f57f
...@@ -376,7 +376,7 @@ class AssessmentPart(models.Model): ...@@ -376,7 +376,7 @@ class AssessmentPart(models.Model):
class AssessmentFeedback(models.Model): class AssessmentFeedback(models.Model):
"""A response to a submission's feedback, judging accuracy or helpfulness.""" """A response to a submission's feedback, judging accuracy or helpfulness."""
submission_uuid = models.CharField(max_length=128, unique=True, db_index=True) submission_uuid = models.CharField(max_length=128, unique=True, db_index=True)
assessments = models.ManyToManyField(Assessment, related_name='assessment_feedback') assessments = models.ManyToManyField(Assessment, related_name='assessment_feedback', default=None)
HELPFULNESS_CHOICES = ( HELPFULNESS_CHOICES = (
(0, 'These results were not at all helpful'), (0, 'These results were not at all helpful'),
(1, 'These results were somewhat helpful'), (1, 'These results were somewhat helpful'),
......
...@@ -907,10 +907,12 @@ def get_assessment_feedback(submission_uuid): ...@@ -907,10 +907,12 @@ def get_assessment_feedback(submission_uuid):
""" """
try: try:
feedback, feedback_created = AssessmentFeedback.objects.get_or_create( feedback = AssessmentFeedback.objects.get(
submission_uuid=submission_uuid submission_uuid=submission_uuid
) )
return AssessmentFeedbackSerializer(feedback).data return AssessmentFeedbackSerializer(feedback).data
except AssessmentFeedback.DoesNotExist:
return None
except DatabaseError: except DatabaseError:
error_message = ( error_message = (
u"An error occurred retrieving assessment feedback for {}." u"An error occurred retrieving assessment feedback for {}."
...@@ -934,15 +936,13 @@ def set_assessment_feedback(must_grade, feedback_dict): ...@@ -934,15 +936,13 @@ def set_assessment_feedback(must_grade, feedback_dict):
Returns: Returns:
The modified or created feedback. The modified or created feedback.
""" """
submission_uuid = feedback_dict.get('submission_uuid', '') submission_uuid = feedback_dict.get('submission_uuid')
if not submission_uuid: if not submission_uuid:
error_message = u"An error occurred creating assessment feedback: bad or missing submission_uuid." error_message = u"An error occurred creating assessment feedback: bad or missing submission_uuid."
logger.exception(error_message) logger.error(error_message)
raise PeerAssessmentInternalError(error_message) raise PeerAssessmentRequestError(error_message)
try: try:
feedback_model = AssessmentFeedback.objects.get_or_create(submission_uuid=submission_uuid) assessments = Assessment.objects.filter(submission__uuid=submission_uuid, score_type="PE")
submission = Submission.objects.get(uuid=submission_uuid)
assessments = Assessment.objects.filter(submission=submission, score_type="PE")
except DatabaseError: except DatabaseError:
error_message = ( error_message = (
u"An error occurred getting database state to set assessment feedback for {}." u"An error occurred getting database state to set assessment feedback for {}."
...@@ -950,12 +950,16 @@ def set_assessment_feedback(must_grade, feedback_dict): ...@@ -950,12 +950,16 @@ def set_assessment_feedback(must_grade, feedback_dict):
) )
logger.exception(error_message) logger.exception(error_message)
raise PeerAssessmentInternalError(error_message) raise PeerAssessmentInternalError(error_message)
feedback_dict['assessments'] = [ assessment.pk for assessment in assessments[:must_grade] ] feedback = AssessmentFeedbackSerializer(data=feedback_dict)
feedback = AssessmentFeedbackSerializer(feedback_model, data=feedback_dict)
if not feedback.is_valid(): if not feedback.is_valid():
raise PeerAssessmentRequestError(feedback.errors) raise PeerAssessmentRequestError(feedback.errors)
try: try:
feedback.save() feedback_model = feedback.save()
# Assessments associated with feedback must be saved after the row is
# committed to the database in order to associated the PKs across both
# tables.
feedback_model.assessments.add(*[assessment.id for assessment in assessments[:must_grade]])
except DatabaseError: except DatabaseError:
error_message = ( error_message = (
u"An error occurred saving assessment feedback for {}." u"An error occurred saving assessment feedback for {}."
......
...@@ -274,6 +274,10 @@ def rubric_from_dict(rubric_dict): ...@@ -274,6 +274,10 @@ def rubric_from_dict(rubric_dict):
class AssessmentFeedbackSerializer(serializers.ModelSerializer): class AssessmentFeedbackSerializer(serializers.ModelSerializer):
submission_uuid = serializers.CharField(source='submission_uuid')
helpfulness = serializers.IntegerField(source='helpfulness')
feedback = serializers.CharField(source='feedback')
assessments = AssessmentSerializer(many=True, default=None, required=False)
class Meta: class Meta:
model = AssessmentFeedback model = AssessmentFeedback
...@@ -281,5 +285,6 @@ class AssessmentFeedbackSerializer(serializers.ModelSerializer): ...@@ -281,5 +285,6 @@ class AssessmentFeedbackSerializer(serializers.ModelSerializer):
'submission_uuid', 'submission_uuid',
'helpfulness', 'helpfulness',
'feedback', 'feedback',
'assessments',
) )
...@@ -24,6 +24,7 @@ class GradeMixin(object): ...@@ -24,6 +24,7 @@ class GradeMixin(object):
context = {} context = {}
if status == "done": if status == "done":
feedback = peer_api.get_assessment_feedback(self.submission_uuid) feedback = peer_api.get_assessment_feedback(self.submission_uuid)
feedback_text = feedback.get('feedback', '') if feedback else ''
max_scores = peer_api.get_rubric_max_scores(self.submission_uuid) max_scores = peer_api.get_rubric_max_scores(self.submission_uuid)
path = 'openassessmentblock/grade/oa_grade_complete.html' path = 'openassessmentblock/grade/oa_grade_complete.html'
assessment_ui_model = self.get_assessment_module('peer-assessment') assessment_ui_model = self.get_assessment_module('peer-assessment')
...@@ -44,7 +45,7 @@ class GradeMixin(object): ...@@ -44,7 +45,7 @@ class GradeMixin(object):
student_submission["uuid"], student_submission["uuid"],
assessment_ui_model["must_be_graded_by"] assessment_ui_model["must_be_graded_by"]
) )
context["feedback_text"] = feedback.get('feedback', '') context["feedback_text"] = feedback_text
context["student_submission"] = student_submission context["student_submission"] = student_submission
context["peer_assessments"] = peer_assessments context["peer_assessments"] = peer_assessments
context["self_assessment"] = self_assessment context["self_assessment"] = self_assessment
...@@ -75,36 +76,33 @@ class GradeMixin(object): ...@@ -75,36 +76,33 @@ class GradeMixin(object):
def feedback_submit(self, data, suffix=''): def feedback_submit(self, data, suffix=''):
"""Attach the Assessment Feedback text to some submission.""" """Attach the Assessment Feedback text to some submission."""
assessment_ui_model = self.get_assessment_module('peer-assessment') or {} assessment_ui_model = self.get_assessment_module('peer-assessment') or {}
assessment_feedback = data.get('feedback', '') assessment_feedback = data.get('feedback', '')
if not assessment_feedback: if not assessment_feedback:
return { return {
'success': False, 'success': False,
'msg': _(u"No feedback given, so none recorded") 'msg': _(u"No feedback given, so none recorded")
} }
peer_assessment_error_message = ''
try: try:
peer_api.set_assessment_feedback( peer_api.set_assessment_feedback(
assessment_ui_model.get('must_grade', 0), assessment_ui_model['must_grade'],
{ {
'submission_uuid': self.submission_uuid, 'submission_uuid': self.submission_uuid,
'feedback': assessment_feedback, 'feedback': assessment_feedback,
'helpfulness': 0 'helpfulness': 0
} }
) )
except peer_api.PeerAssessmentInternalError, msg: except (
peer_assessment_error_message = msg peer_api.PeerAssessmentInternalError,
except peer_api.PeerAsessmentRequestError, msg: peer_api.PeerAssessmentRequestError
peer_assessment_error_message = msg ):
if peer_assessment_error_message:
return { return {
'success': False, 'success': False,
'msg': peer_assessment_error_message, 'msg': _(
u"Assessment Feedback could not be saved due to an internal "
u"server error."
),
} }
else:
# Success!
return { return {
'success': True, 'success': True,
'msg': _(u"Feedback saved!") 'msg': _(u"Feedback saved!")
......
if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}OpenAssessment.BaseUI=function(runtime,element,server){this.runtime=runtime;this.element=element;this.server=server};OpenAssessment.BaseUI.prototype={setUpCollapseExpand:function(parentSel,onExpand){parentSel.find(".ui-toggle-visibility__control").click(function(eventData){var sel=$(eventData.target).closest(".ui-toggle-visibility");if(sel.hasClass("is--collapsed")&&onExpand!==undefined){onExpand()}sel.toggleClass("is--collapsed")})},load:function(){this.renderSubmissionStep();this.renderPeerAssessmentStep();this.renderSelfAssessmentStep();this.renderGradeStep()},renderSubmissionStep:function(){var ui=this;this.server.render("submission").done(function(html){$("#openassessment__response",ui.element).replaceWith(html);var sel=$("#openassessment__response",ui.element);ui.setUpCollapseExpand(sel);ui.responseChanged();sel.find("#submission__answer__value").keyup(function(eventData){ui.responseChanged()});sel.find("#step--response__submit").click(function(eventObject){eventObject.preventDefault();ui.submit()});sel.find("#submission__save").click(function(eventObject){eventObject.preventDefault();ui.save()})}).fail(function(errMsg){ui.showLoadError("response")})},responseChanged:function(){var blankSubmission=$("#submission__answer__value",this.element).val()==="";$("#step--response__submit",this.element).toggleClass("is--disabled",blankSubmission);$("#submission__save",this.element).toggleClass("is--disabled",blankSubmission)},renderPeerAssessmentStep:function(){var ui=this;this.server.render("peer_assessment").done(function(html){$("#openassessment__peer-assessment",ui.element).replaceWith(html);var sel=$("#openassessment__peer-assessment",ui.element);ui.setUpCollapseExpand(sel,$.proxy(ui.renderContinuedPeerAssessmentStep,ui));sel.find("#peer-assessment--001__assessment").change(function(){var numChecked=$("input[type=radio]:checked",this).length;var numAvailable=$(".field--radio.assessment__rubric__question",this).length;$("#peer-assessment--001__assessment__submit",ui.element).toggleClass("is--disabled",numChecked!=numAvailable)});sel.find("#peer-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();ui.peerAssess()})}).fail(function(errMsg){ui.showLoadError("peer-assessment")})},renderContinuedPeerAssessmentStep:function(){var ui=this;this.server.renderContinuedPeer().done(function(html){$("#openassessment__peer-assessment",ui.element).replaceWith(html);var sel=$("#openassessment__peer-assessment",ui.element);ui.setUpCollapseExpand(sel);sel.find("#peer-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();ui.continuedPeerAssess()});sel.find("#peer-assessment--001__assessment").change(function(){var numChecked=$("input[type=radio]:checked",this).length;var numAvailable=$(".field--radio.assessment__rubric__question",this).length;$("#peer-assessment--001__assessment__submit",ui.element).toggleClass("is--disabled",numChecked!=numAvailable)})}).fail(function(errMsg){ui.showLoadError("peer-assessment")})},renderSelfAssessmentStep:function(){var ui=this;this.server.render("self_assessment").done(function(html){$("#openassessment__self-assessment",ui.element).replaceWith(html);var sel=$("#openassessment__self-assessment",ui.element);ui.setUpCollapseExpand(sel);$("#self-assessment--001__assessment",ui.element).change(function(){var numChecked=$("input[type=radio]:checked",this).length;var numAvailable=$(".field--radio.assessment__rubric__question",this).length;$("#self-assessment--001__assessment__submit",ui.element).toggleClass("is--disabled",numChecked!=numAvailable)});sel.find("#self-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();ui.selfAssess()})}).fail(function(errMsg){ui.showLoadError("self-assessment")})},renderGradeStep:function(){var ui=this;this.server.render("grade").done(function(html){$("#openassessment__grade",ui.element).replaceWith(html);var sel=$("#openassessment__grade",ui.element);ui.setUpCollapseExpand(sel)}).fail(function(errMsg){ui.showLoadError("grade",errMsg)})},save:function(){var submission=$("#submission__answer__value",this.element).val();var ui=this;this.setSaveStatus("Saving...");this.toggleActionError("save",null);this.server.save(submission).done(function(){ui.setSaveStatus("Saved but not submitted")}).fail(function(errMsg){ui.setSaveStatus("Error");ui.toggleActionError("save",errMsg)})},setSaveStatus:function(msg){$("#response__save_status h3",this.element).html(msg)},submit:function(){var submission=$("#submission__answer__value",this.element).val();var ui=this;this.toggleActionError("response",null);this.server.submit(submission).done(function(studentId,attemptNum){ui.renderSubmissionStep();ui.renderPeerAssessmentStep()}).fail(function(errCode,errMsg){ui.toggleActionError("submit",errMsg)})},peerAssess:function(){var ui=this;ui.peerAssessRequest(function(){ui.renderPeerAssessmentStep();ui.renderSelfAssessmentStep();ui.renderGradeStep()})},continuedPeerAssess:function(){var ui=this;ui.peerAssessRequest(function(){ui.renderContinuedPeerAssessmentStep();ui.renderGradeStep()})},peerAssessRequest:function(successFunction){var submissionId=$("span#peer_submission_uuid",this.element)[0].innerHTML.trim();var optionsSelected={};$("#peer-assessment--001__assessment input[type=radio]:checked",this.element).each(function(index,sel){optionsSelected[sel.name]=sel.value});var feedback=$("#assessment__rubric__question--feedback__value",this.element).val();var ui=this;this.toggleActionError("peer",null);this.server.peerAssess(submissionId,optionsSelected,feedback).done(successFunction).fail(function(errMsg){ui.toggleActionError("peer",errMsg)})},selfAssess:function(){var submissionId=$("span#self_submission_uuid",this.element)[0].innerHTML.trim();var optionsSelected={};$("#self-assessment--001__assessment input[type=radio]:checked",this.element).each(function(index,sel){optionsSelected[sel.name]=sel.value});var ui=this;this.toggleActionError("self",null);this.server.selfAssess(submissionId,optionsSelected).done(function(){ui.renderPeerAssessmentStep();ui.renderSelfAssessmentStep();ui.renderGradeStep()}).fail(function(errMsg){ui.toggleActionError("self",errMsg)})},toggleActionError:function(type,msg){var container=null;if(type=="save"){container=".response__submission__actions"}else if(type=="submit"){container=".step__actions"}else if(type=="peer"){container=".peer-assessment__actions"}else if(type=="self"){container=".self-assessment__actions"}if(container===null){if(msg!==null){console.log(msg)}}else{var msgHtml=msg===null?"":msg;$(container+" .message__content").html("<p>"+msg+"</p>");$(container).toggleClass("has--error",msg!==null)}},showLoadError:function(step){var container="#openassessment__"+step;$(container).toggleClass("has--error",true);$(container+" .step__status__value i").removeClass().addClass("icon-warning-sign");$(container+" .step__status__value .copy").html("Unable to Load")}};function OpenAssessmentBlock(runtime,element){$(function($){var server=new OpenAssessment.Server(runtime,element);var ui=new OpenAssessment.BaseUI(runtime,element,server);ui.load()})}if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}OpenAssessment.StudioUI=function(runtime,element,server){this.runtime=runtime;this.server=server;this.codeBox=CodeMirror.fromTextArea($(element).find(".openassessment-editor").first().get(0),{mode:"xml",lineNumbers:true,lineWrapping:true});var ui=this;$(element).find(".openassessment-save-button").click(function(eventData){ui.save()});$(element).find(".openassessment-cancel-button").click(function(eventData){ui.cancel()})};OpenAssessment.StudioUI.prototype={load:function(){var ui=this;this.server.loadXml().done(function(xml){ui.codeBox.setValue(xml)}).fail(function(msg){ui.showError(msg)})},save:function(){var ui=this;this.server.checkReleased().done(function(isReleased){if(isReleased){ui.confirmPostReleaseUpdate($.proxy(ui.updateXml,ui))}else{ui.updateXml()}}).fail(function(errMsg){console.log(errMsg)})},confirmPostReleaseUpdate:function(onConfirm){var msg="This problem has already been released. Any changes will apply only to future assessments.";if(confirm(msg)){onConfirm()}},updateXml:function(){this.runtime.notify("save",{state:"start"});var xml=this.codeBox.getValue();var ui=this;this.server.updateXml(xml).done(function(){ui.runtime.notify("save",{state:"end"});ui.load()}).fail(function(msg){ui.showError(msg)})},cancel:function(){this.runtime.notify("cancel",{})},showError:function(errorMsg){this.runtime.notify("error",{msg:errorMsg})}};function OpenAssessmentEditor(runtime,element){$(function($){var server=new OpenAssessment.Server(runtime,element);var ui=new OpenAssessment.StudioUI(runtime,element,server);ui.load()})}if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}OpenAssessment.Server=function(runtime,element){this.runtime=runtime;this.element=element};OpenAssessment.Server.prototype={url:function(handler){return this.runtime.handlerUrl(this.element,handler)},render:function(component){var url=this.url("render_"+component);return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html"}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},renderContinuedPeer:function(){var url=this.url("render_peer_assessment");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{continue_grading:true}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},submit:function(submission){var url=this.url("submit");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){var success=data[0];if(success){var studentId=data[1];var attemptNum=data[2];defer.resolveWith(this,[studentId,attemptNum])}else{var errorNum=data[1];var errorMsg=data[2];defer.rejectWith(this,[errorNum,errorMsg])}}).fail(function(data){defer.rejectWith(this,["AJAX","Could not contact server."])})}).promise()},save:function(submission){var url=this.url("save_submission");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},peerAssess:function(submissionId,optionsSelected,feedback){var url=this.url("peer_assess");var payload=JSON.stringify({submission_uuid:submissionId,options_selected:optionsSelected,feedback:feedback});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},selfAssess:function(submissionId,optionsSelected){var url=this.url("self_assess");var payload=JSON.stringify({submission_uuid:submissionId,options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})})},loadXml:function(){var url=this.url("xml");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.xml])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},updateXml:function(xml){var url=this.url("update_xml");var payload=JSON.stringify({xml:xml});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},checkReleased:function(){var url=this.url("check_released");var payload='""';return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.is_released])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()}}; if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}OpenAssessment.BaseUI=function(runtime,element,server){this.runtime=runtime;this.element=element;this.server=server};OpenAssessment.BaseUI.prototype={setUpCollapseExpand:function(parentSel,onExpand){parentSel.find(".ui-toggle-visibility__control").click(function(eventData){var sel=$(eventData.target).closest(".ui-toggle-visibility");if(sel.hasClass("is--collapsed")&&onExpand!==undefined){onExpand()}sel.toggleClass("is--collapsed")})},load:function(){this.renderSubmissionStep();this.renderPeerAssessmentStep();this.renderSelfAssessmentStep();this.renderGradeStep()},renderSubmissionStep:function(){var ui=this;this.server.render("submission").done(function(html){$("#openassessment__response",ui.element).replaceWith(html);var sel=$("#openassessment__response",ui.element);ui.setUpCollapseExpand(sel);ui.responseChanged();sel.find("#submission__answer__value").keyup(function(eventData){ui.responseChanged()});sel.find("#step--response__submit").click(function(eventObject){eventObject.preventDefault();ui.submit()});sel.find("#submission__save").click(function(eventObject){eventObject.preventDefault();ui.save()})}).fail(function(errMsg){ui.showLoadError("response")})},responseChanged:function(){var blankSubmission=$("#submission__answer__value",this.element).val()==="";$("#step--response__submit",this.element).toggleClass("is--disabled",blankSubmission);$("#submission__save",this.element).toggleClass("is--disabled",blankSubmission)},renderPeerAssessmentStep:function(){var ui=this;this.server.render("peer_assessment").done(function(html){$("#openassessment__peer-assessment",ui.element).replaceWith(html);var sel=$("#openassessment__peer-assessment",ui.element);ui.setUpCollapseExpand(sel,$.proxy(ui.renderContinuedPeerAssessmentStep,ui));sel.find("#peer-assessment--001__assessment").change(function(){var numChecked=$("input[type=radio]:checked",this).length;var numAvailable=$(".field--radio.assessment__rubric__question",this).length;$("#peer-assessment--001__assessment__submit",ui.element).toggleClass("is--disabled",numChecked!=numAvailable)});sel.find("#peer-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();ui.peerAssess()})}).fail(function(errMsg){ui.showLoadError("peer-assessment")})},renderContinuedPeerAssessmentStep:function(){var ui=this;this.server.renderContinuedPeer().done(function(html){$("#openassessment__peer-assessment",ui.element).replaceWith(html);var sel=$("#openassessment__peer-assessment",ui.element);ui.setUpCollapseExpand(sel);sel.find("#peer-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();ui.continuedPeerAssess()});sel.find("#peer-assessment--001__assessment").change(function(){var numChecked=$("input[type=radio]:checked",this).length;var numAvailable=$(".field--radio.assessment__rubric__question",this).length;$("#peer-assessment--001__assessment__submit",ui.element).toggleClass("is--disabled",numChecked!=numAvailable)})}).fail(function(errMsg){ui.showLoadError("peer-assessment")})},renderSelfAssessmentStep:function(){var ui=this;this.server.render("self_assessment").done(function(html){$("#openassessment__self-assessment",ui.element).replaceWith(html);var sel=$("#openassessment__self-assessment",ui.element);ui.setUpCollapseExpand(sel);$("#self-assessment--001__assessment",ui.element).change(function(){var numChecked=$("input[type=radio]:checked",this).length;var numAvailable=$(".field--radio.assessment__rubric__question",this).length;$("#self-assessment--001__assessment__submit",ui.element).toggleClass("is--disabled",numChecked!=numAvailable)});sel.find("#self-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();ui.selfAssess()})}).fail(function(errMsg){ui.showLoadError("self-assessment")})},renderGradeStep:function(){var ui=this;this.server.render("grade").done(function(html){$("#openassessment__grade",ui.element).replaceWith(html);var sel=$("#openassessment__grade",ui.element);ui.setUpCollapseExpand(sel);sel.find("#feedback__submit").click(function(eventObject){eventObject.preventDefault();ui.feedback_assess()})}).fail(function(errMsg){ui.showLoadError("grade",errMsg)})},save:function(){var submission=$("#submission__answer__value",this.element).val();var ui=this;this.setSaveStatus("Saving...");this.toggleActionError("save",null);this.server.save(submission).done(function(){ui.setSaveStatus("Saved but not submitted")}).fail(function(errMsg){ui.setSaveStatus("Error");ui.toggleActionError("save",errMsg)})},setSaveStatus:function(msg){$("#response__save_status h3",this.element).html(msg)},submit:function(){var submission=$("#submission__answer__value",this.element).val();var ui=this;this.toggleActionError("response",null);this.server.submit(submission).done(function(studentId,attemptNum){ui.renderSubmissionStep();ui.renderPeerAssessmentStep()}).fail(function(errCode,errMsg){ui.toggleActionError("submit",errMsg)})},feedback_assess:function(){var feedback=$("#feedback__remarks__value",this.element).val();var ui=this;this.server.feedback_submit(feedback).done(console.log("Feedback to the assessments submitted, thanks!")).fail(function(errMsg){ui.toggleActionError("feedback_assess",errMsg)})},peerAssess:function(){var ui=this;ui.peerAssessRequest(function(){ui.renderPeerAssessmentStep();ui.renderSelfAssessmentStep();ui.renderGradeStep()})},continuedPeerAssess:function(){var ui=this;ui.peerAssessRequest(function(){ui.renderContinuedPeerAssessmentStep();ui.renderGradeStep()})},peerAssessRequest:function(successFunction){var submissionId=$("span#peer_submission_uuid",this.element)[0].innerHTML.trim();var optionsSelected={};$("#peer-assessment--001__assessment input[type=radio]:checked",this.element).each(function(index,sel){optionsSelected[sel.name]=sel.value});var feedback=$("#assessment__rubric__question--feedback__value",this.element).val();var ui=this;this.toggleActionError("peer",null);this.server.peerAssess(submissionId,optionsSelected,feedback).done(successFunction).fail(function(errMsg){ui.toggleActionError("peer",errMsg)})},selfAssess:function(){var submissionId=$("span#self_submission_uuid",this.element)[0].innerHTML.trim();var optionsSelected={};$("#self-assessment--001__assessment input[type=radio]:checked",this.element).each(function(index,sel){optionsSelected[sel.name]=sel.value});var ui=this;this.toggleActionError("self",null);this.server.selfAssess(submissionId,optionsSelected).done(function(){ui.renderPeerAssessmentStep();ui.renderSelfAssessmentStep();ui.renderGradeStep()}).fail(function(errMsg){ui.toggleActionError("self",errMsg)})},toggleActionError:function(type,msg){var container=null;if(type=="save"){container=".response__submission__actions"}else if(type=="submit"){container=".step__actions"}else if(type=="peer"){container=".peer-assessment__actions"}else if(type=="self"){container=".self-assessment__actions"}if(container===null){if(msg!==null){console.log(msg)}}else{var msgHtml=msg===null?"":msg;$(container+" .message__content").html("<p>"+msg+"</p>");$(container).toggleClass("has--error",msg!==null)}},showLoadError:function(step){var container="#openassessment__"+step;$(container).toggleClass("has--error",true);$(container+" .step__status__value i").removeClass().addClass("icon-warning-sign");$(container+" .step__status__value .copy").html("Unable to Load")}};function OpenAssessmentBlock(runtime,element){$(function($){var server=new OpenAssessment.Server(runtime,element);var ui=new OpenAssessment.BaseUI(runtime,element,server);ui.load()})}if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}OpenAssessment.StudioUI=function(runtime,element,server){this.runtime=runtime;this.server=server;this.codeBox=CodeMirror.fromTextArea($(element).find(".openassessment-editor").first().get(0),{mode:"xml",lineNumbers:true,lineWrapping:true});var ui=this;$(element).find(".openassessment-save-button").click(function(eventData){ui.save()});$(element).find(".openassessment-cancel-button").click(function(eventData){ui.cancel()})};OpenAssessment.StudioUI.prototype={load:function(){var ui=this;this.server.loadXml().done(function(xml){ui.codeBox.setValue(xml)}).fail(function(msg){ui.showError(msg)})},save:function(){var ui=this;this.server.checkReleased().done(function(isReleased){if(isReleased){ui.confirmPostReleaseUpdate($.proxy(ui.updateXml,ui))}else{ui.updateXml()}}).fail(function(errMsg){console.log(errMsg)})},confirmPostReleaseUpdate:function(onConfirm){var msg="This problem has already been released. Any changes will apply only to future assessments.";if(confirm(msg)){onConfirm()}},updateXml:function(){this.runtime.notify("save",{state:"start"});var xml=this.codeBox.getValue();var ui=this;this.server.updateXml(xml).done(function(){ui.runtime.notify("save",{state:"end"});ui.load()}).fail(function(msg){ui.showError(msg)})},cancel:function(){this.runtime.notify("cancel",{})},showError:function(errorMsg){this.runtime.notify("error",{msg:errorMsg})}};function OpenAssessmentEditor(runtime,element){$(function($){var server=new OpenAssessment.Server(runtime,element);var ui=new OpenAssessment.StudioUI(runtime,element,server);ui.load()})}if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}OpenAssessment.Server=function(runtime,element){this.runtime=runtime;this.element=element};OpenAssessment.Server.prototype={url:function(handler){return this.runtime.handlerUrl(this.element,handler)},render:function(component){var url=this.url("render_"+component);return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html"}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},renderContinuedPeer:function(){var url=this.url("render_peer_assessment");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{continue_grading:true}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},submit:function(submission){var url=this.url("submit");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){var success=data[0];if(success){var studentId=data[1];var attemptNum=data[2];defer.resolveWith(this,[studentId,attemptNum])}else{var errorNum=data[1];var errorMsg=data[2];defer.rejectWith(this,[errorNum,errorMsg])}}).fail(function(data){defer.rejectWith(this,["AJAX","Could not contact server."])})}).promise()},save:function(submission){var url=this.url("save_submission");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},feedback_submit:function(feedback){var url=this.url("feedback_submit");var payload=JSON.stringify({feedback:feedback});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},peerAssess:function(submissionId,optionsSelected,feedback){var url=this.url("peer_assess");var payload=JSON.stringify({submission_uuid:submissionId,options_selected:optionsSelected,feedback:feedback});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},selfAssess:function(submissionId,optionsSelected){var url=this.url("self_assess");var payload=JSON.stringify({submission_uuid:submissionId,options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})})},loadXml:function(){var url=this.url("xml");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.xml])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},updateXml:function(xml){var url=this.url("update_xml");var payload=JSON.stringify({xml:xml});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()},checkReleased:function(){var url=this.url("check_released");var payload='""';return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.is_released])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,["Could not contact server."])})}).promise()}};
\ No newline at end of file \ No newline at end of file
...@@ -322,12 +322,13 @@ OpenAssessment.BaseUI.prototype = { ...@@ -322,12 +322,13 @@ OpenAssessment.BaseUI.prototype = {
feedback_assess: function() { feedback_assess: function() {
// Send the submission to the server // Send the submission to the server
var feedback = $('#feedback__remarks__value', this.element).val(); var feedback = $('#feedback__remarks__value', this.element).val();
var ui = this;
this.server.feedback_submit(feedback).done( this.server.feedback_submit(feedback).done(
// When we have successfully sent the submission, textarea no longer editable // When we have successfully sent the submission, textarea no longer editable
console.log("Feedback to the assessments submitted, thanks!") console.log("Feedback to the assessments submitted, thanks!")
).fail(function(errMsg) { ).fail(function(errMsg) {
// TODO: display to the user // TODO: display to the user
console.log(errMsg); ui.toggleActionError('feedback_assess', errMsg);
}); });
}, },
......
...@@ -163,6 +163,20 @@ OpenAssessment.Server.prototype = { ...@@ -163,6 +163,20 @@ OpenAssessment.Server.prototype = {
/** /**
* Send feedback on assessments to the XBlock. * Send feedback on assessments to the XBlock.
* Args:
* feedback: The feedback given on a series of assessments associated
* with this current submission.
*
* Returns:
* A JQuery promise, which resolves with no args if successful and
* fails with an error message otherwise.
*
* Example:
* server.feedback_submit("I dislike my reviews.").done(
* console.log("Success!");
* ).fail(function(errMsg) {
* console.log("Error: " + errMsg);
* });
*/ */
feedback_submit: function(feedback) { feedback_submit: function(feedback) {
var url = this.url('feedback_submit'); var url = this.url('feedback_submit');
......
...@@ -11,7 +11,7 @@ export DJANGO_SETTINGS_MODULE="settings.dev" ...@@ -11,7 +11,7 @@ export DJANGO_SETTINGS_MODULE="settings.dev"
# Create the database # Create the database
echo "Updating the database..." echo "Updating the database..."
python manage.py syncdb --migrate --noinput -v 0 python manage.py syncdb --migrate -v 0
echo "Starting server..." echo "Starting server..."
python manage.py runserver_plus "${@:1}" python manage.py runserver_plus "${@:1}"
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