Commit c217e3c3 by gradyward

TIM 386 -- Wire up UI messages

Adds Unit Tests to UI messages and fixes Two syntax errors

Added Test Cases and changed return Methodology

Removed Comments that were not in Style

Added cases for Student Training

TIM 386 -- Wire Up UI Messages
parent 09807a80
{% load i18n %}
{% spaceless %}
<div id="openassessment__message" class="openassessment__message message">
<h3 class="message__title">
{% if not_yet_open %}
{% trans "This Task Is Not Yet Available" %}
{% else %}
{% trans "This Assignment Has Closed" %}
{% endif %}
</h3>
<div class="message__content">
<p>
{% if not_yet_open %}
{% trans "Check back to complete the assignment once this section has opened." %}
{% else %}
{% trans "One or more deadlines for this assignment have passed. You will receive an incomplete grade for this assignment." %}
{% endif %}
</p>
</div>
</div>
{% endspaceless %}
\ No newline at end of file
{% load i18n %}
{% spaceless %}
<div id="openassessment__message" class="openassessment__message message">
<h3 class="message__title">{% trans "You Have Completed This Assignment" %} </h3>
<div class="message__content">
<p>
{% if waiting %}
{% trans "Your grade will be available when your peers have completed their assessments of your response." %}
{% else %}
{% blocktrans %}
Review <a data-behavior="ui-scroll" href="#openassessment__grade"> your grade and your assessment details</a>.
{% endblocktrans %}
{% endif %}
</p>
</div>
</div>
{% endspaceless %}
\ No newline at end of file
{% load i18n %}
{% spaceless %}
<div id="openassessment__message" class="openassessment__message message">
<div class="message__content">
<p>
{% if approaching %}
{% blocktrans %}
Assignment submissions will close soon. To receive a grade, first provide a response to the question, then complete the steps below the <strong>Your Response</strong> field.
{% endblocktrans %}
{% else %}
{% blocktrans %}
This assignment has several steps. In the first step, you'll provide a response to the question. The other steps appear below the <strong>Your Response</strong> field.
{% endblocktrans %}
{% endif %}
</p>
</div>
</div>
{% endspaceless %}
\ No newline at end of file
{% load i18n %}
{% spaceless %}
<div id="openassessment__message" class="openassessment__message message">
<h3 class="message__title">
{% if waiting %}
{% trans "Waiting for Peer Submissions" %}
{% elif peer_not_released %}
{% trans "The Period For Peer Evaluation Has Not Started" %}
{% else %}
{% trans "Your Response Has Been Submitted For Peer Assessment" %}
{% endif %}
</h3>
<div class="message__content">
<p>
{% if peer_not_released %}
{% trans "Check back later when the assessment period has opened." %}
{% else %}
{% if peer_approaching %}
<strong> {% trans "Peer evaluation of this assignment will close soon. " %} </strong>
{% endif %}
{% if waiting %}
{% trans "All submitted peer responses have been assessed. Check back later to see if more students have submitted responses. " %}
{% endif %}
{% if has_self %}
{% blocktrans %}
You'll receive your grade after you complete the <a data-behavior="ui-scroll" href=#openassessment__peer-assessment">peer assessment</a> and <a data-behavior="ui-scroll" href="#openassessment__self-assessment">self assessment</a> steps, and after your peers have assessed your response.
{% endblocktrans %}
{% else %}
{% blocktrans %}
You'll receive your grade after you complete the <a data-behavior="ui-scroll" href="#openassessment__peer-assessment">peer assessment</a> step.
{% endblocktrans %}
{% endif %}
{% endif %}
</p>
</div>
</div>
{% endspaceless %}
\ No newline at end of file
{% load i18n %}
{% spaceless %}
<div id="openassessment__message" class="openassessment__message message">
<h3 class="message__title">
{% if self_not_released %}
{% trans "The Period For Self Evaluation Has Not Started" %}
{% elif has_peer %}
{% trans "Your Response Has Been Submitted For Peer Assessment" %}
{% else %}
{% trans "Your Response Is Ready For Self Assessment" %}
{% endif %}
</h3>
<div class="message__content">
<p>
{% if self_not_released %}
{% trans "Check back later when the assessment period has opened." %}
{% else %}
{% if self_approaching %}
<strong> {% trans "Self evaluation of this assignment will close soon. " %} </strong>
{% endif %}
{% if has_peer %}
{% blocktrans %}
You'll receive your grade after the required number of your peers have assessed your response and you complete the <a data-behavior="ui-scroll" href="#openassessment__self-assessment">self assessment</a> step.
{% endblocktrans %}
{% else %}
{% blocktrans %}
You'll receive your grade after you complete the <a data-behavior="ui-scroll" href="#openassessment__self-assessment">self assessment</a> step.
{% endblocktrans %}
{% endif %}
{% endif %}
</p>
</div>
</div>
{% endspaceless %}
\ No newline at end of file
{% load i18n %}
{% spaceless %}
<div id="openassessment__message" class="openassessment__message message">
<div class="message__content">
<p>
{% if approaching %}
{% trans "Student training for peer assessment will close soon. " %}
{% endif %}
{% trans "Complete the student training section to move on to peer assessment." %}
</p>
</div>
</div>
{% endspaceless %}
\ No newline at end of file
{% load i18n %}
{% spaceless %}
<div id="openassessment__message" class="openassessment__message message">
<h3 class="message__title">{% trans "Instructions Unavailable" %} </h3>
<div class="message__content">
<p> {% trans "The instructions for this step could not be loaded." %}</p>
</div>
</div>
{% endspaceless %}
\ No newline at end of file
...@@ -20,14 +20,16 @@ ...@@ -20,14 +20,16 @@
</ol> </ol>
</nav> </nav>
<div class="wrapper-openassessment__message">
{% block message %} {% block message %}
<!-- if the problem is unstarted or response hasn't been submitted -->
<div id="openassessment__message" class="openassessment__message message"> <div id="openassessment__message" class="openassessment__message message">
<h3 class="message__title">Instructions</h3>
<div class="message__content"> <div class="message__content">
<p>{% trans "This assignment has several steps. In the first step, you'll provide a response to the question. The other steps appear below the <strong>Your Response</strong> field." %}</p> <p>{% trans "This assignment has several steps. In the first step, you'll provide a response to the question. The other steps appear below the Your Response field." %}</p>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
</div>
<div class="wrapper--openassessment__prompt"> <div class="wrapper--openassessment__prompt">
{% if question %} {% if question %}
......
"""
Message step in the OpenAssessment XBlock.
"""
import datetime as dt
import pytz
from xblock.core import XBlock
class MessageMixin(object):
"""
Message Mixin introduces all handlers for displaying the banner message
MessageMixin is a Mixin for the OpenAssessmentBlock. Functions in the
MessageMixin call into the OpenAssessmentBlock functions and will not work
outside of OpenAssessmentBlock.
"""
@XBlock.handler
def render_message(self, data, suffix=''):
"""
Render the message step.
Args:
data: Not used.
Kwargs:
suffix: Not used.
Returns:
unicode: HTML content of the message banner.
"""
# Retrieve the status of the workflow and information about deadlines.
workflow = self.get_workflow_info()
deadline_info = self._get_deadline_info()
# Finds the cannonical status of the workflow and the is_closed status of the problem
status = workflow.get('status')
is_closed = deadline_info.get('general').get('is_closed')
# Finds the status_information which describes the closed status of the current step (defaults to submission)
status_info = deadline_info.get(status, deadline_info.get("submission"))
status_is_closed = status_info.get('is_closed')
# Default context is empty
context = {}
# Default path leads to an "instruction-unavailable" block
path = 'openassessmentblock/message/oa_message_unavailable.html'
# Render the instruction message based on the status of the workflow
# and the closed status.
if status == "done" or status == "waiting":
path, context = self.render_message_complete(status)
elif is_closed or status_is_closed:
path, context = self.render_message_closed(status_info)
elif status == "self":
path, context = self.render_message_self(deadline_info)
elif status == "peer":
path, context = self.render_message_peer(deadline_info)
elif status == "training":
path, context = self.render_message_training(deadline_info)
elif status is None:
path, context = self.render_message_open(deadline_info)
return self.render_assessment(path, context)
def render_message_complete(self, status):
"""
Renders the "Complete" message state (Either Waiting or Done)
Args:
status (String): indicates the canonical status of the workflow
Returns:
The path (String) and context (dict) to render the "Complete" message template
"""
context = {
"waiting": (status == "waiting")
}
return 'openassessmentblock/message/oa_message_complete.html', context
def render_message_training(self, deadline_info):
"""
Renders the "Student-Training" message state (Either Waiting or Done)
Args:
status (String): indicates the canonical status of the workflow
Returns:
The path (String) and context (dict) to render the "Complete" message template
"""
approaching = deadline_info.get('training').get('approaching')
context = {
'approaching': approaching
}
return 'openassessmentblock/message/oa_message_training.html', context
def render_message_closed(self, status_info):
"""
Renders the "Closed" message state
Args:
status_info (dict): The dictionary describing the closed status of the current step
Returns:
The path (String) and context (dict) to render the "Closed" template
"""
reason = status_info.get("reason")
context = {
"not_yet_open": (reason == "start")
}
return 'openassessmentblock/message/oa_message_closed.html', context
def render_message_self(self, deadline_info):
"""
Renders the "Self" message state
Args:
deadline_info (dict): The dictionary of boolean assessment near/closed states
Returns:
The path (String) and context (dict) to render the "Self" template
"""
has_peer = 'peer-assessment' in self.assessment_steps
self_info = deadline_info.get("self")
context = {
"has_peer": has_peer,
"self_approaching": self_info.get("approaching"),
"self_closed": self_info.get("is_closed"),
"self_not_released": (self_info.get("reason") == "start")
}
return 'openassessmentblock/message/oa_message_self.html', context
def render_message_peer(self, deadline_info):
"""
Renders the "Peer" message state
Args:
deadline_info (dict): The dictionary of boolean assessment near/closed states
Returns:
The path (String) and context (dict) to render the "Peer" template
"""
#Uses a static field in the XBlock to determine if the PeerAssessment Block was able to pick up an assessment.
waiting = self.no_peers
has_self = 'self-assessment' in self.assessment_steps
peer_info = deadline_info.get("peer")
context = {
"has_self": has_self,
"waiting": waiting,
"peer_approaching": peer_info.get("approaching"),
"peer_closed": peer_info.get("is_closed"),
"peer_not_released": (peer_info.get("reason") == "start")
}
return 'openassessmentblock/message/oa_message_peer.html', context
def render_message_open(self, deadline_info):
"""
Renders the "Open" message state
Args:
deadline_info (dict): The dictionary of boolean assessment near/closed states
Returns:
The path (String) and context (dict) to render the "Open" template
"""
submission_approaching = deadline_info.get("submission").get("approaching")
context = {
"approaching": submission_approaching
}
return 'openassessmentblock/message/oa_message_open.html', context
def _get_deadline_info(self):
"""
Get detailed information about the standing of all deadlines.
Args:
None.
Returns:
dict with the following elements
"submission" : dictionary on submission closure of this^ form
"general" : dictionary on problem (all elements) closure of this^ form
"peer": dictionary on peer closure of this^ form *If Assessment has a Peer Section*
"self": dictionary on self closure of this^ form *If Assessment has a Self Section*
this^ form:
"is_closed": (bool) Indicating whether or not that section has closed
"reason": (str) The reason that the section is closed (None if !is_closed)
"approaching": (bool) Indicates whether or not the section deadline is within a day.
"""
# Methods which use datetime.deltatime to figure out if a deadline is approaching.
now = dt.datetime.utcnow().replace(tzinfo=pytz.utc)
def _is_approaching(date):
# Determines if the deadline is within one day of now. (Approaching = True if so)
delta = date - now
return delta.days == 0
# problem_info has form (is_closed, reason, start_date, due_date)
problem_info = self.is_closed()
# submission_info has form (is_closed, reason, start_date, due_date)
submission_info = self.is_closed("submission")
# The information we will always pass on to the user. Adds additional dicts on peer and self if applicable.
deadline_info = {
"submission": {
"is_closed": submission_info[0],
"reason": submission_info[1],
"approaching": _is_approaching(submission_info[3])
},
"general": {
"is_closed": problem_info[0],
"reason": problem_info[1],
"approaching": _is_approaching(problem_info[3])
}
}
has_training = 'student-training' in self.assessment_steps
if has_training:
training_info = self.is_closed("student-training")
training_dict = {
"training": {
"is_closed": training_info[0],
"reason": training_info[1],
"approaching": _is_approaching(training_info[3])
}
}
deadline_info.update(training_dict)
has_peer = 'peer-assessment' in self.assessment_steps
# peer_info has form (is_closed, reason, start_date, due_date)
if has_peer:
peer_info = self.is_closed("peer-assessment")
peer_dict = {
"peer": {
"is_closed": peer_info[0],
"reason": peer_info[1],
"approaching": _is_approaching(peer_info[3])
}
}
deadline_info.update(peer_dict)
has_self = 'self-assessment' in self.assessment_steps
# self_info has form (is_closed, reason, start_date, due_date)
if has_self:
self_info = self.is_closed("self-assessment")
self_dict = {
"self": {
"is_closed": self_info[0],
"reason": self_info[1],
"approaching": _is_approaching(self_info[3])
}
}
deadline_info.update(self_dict)
return deadline_info
...@@ -16,6 +16,7 @@ from xblock.fragment import Fragment ...@@ -16,6 +16,7 @@ from xblock.fragment import Fragment
from openassessment.xblock.grade_mixin import GradeMixin from openassessment.xblock.grade_mixin import GradeMixin
from openassessment.xblock.defaults import * # pylint: disable=wildcard-import, unused-wildcard-import from openassessment.xblock.defaults import * # pylint: disable=wildcard-import, unused-wildcard-import
from openassessment.xblock.message_mixin import MessageMixin
from openassessment.xblock.peer_assessment_mixin import PeerAssessmentMixin from openassessment.xblock.peer_assessment_mixin import PeerAssessmentMixin
from openassessment.xblock.lms_mixin import LmsCompatibilityMixin from openassessment.xblock.lms_mixin import LmsCompatibilityMixin
from openassessment.xblock.self_assessment_mixin import SelfAssessmentMixin from openassessment.xblock.self_assessment_mixin import SelfAssessmentMixin
...@@ -81,6 +82,7 @@ def load(path): ...@@ -81,6 +82,7 @@ def load(path):
class OpenAssessmentBlock( class OpenAssessmentBlock(
XBlock, XBlock,
MessageMixin,
SubmissionMixin, SubmissionMixin,
PeerAssessmentMixin, PeerAssessmentMixin,
SelfAssessmentMixin, SelfAssessmentMixin,
...@@ -148,7 +150,7 @@ class OpenAssessmentBlock( ...@@ -148,7 +150,7 @@ class OpenAssessmentBlock(
has_saved = Boolean( has_saved = Boolean(
default=False, default=False,
scope=Scope.user_state, scope=Scope.user_state,
help="Indicates whether the user has saved a response" help="Indicates whether the user has saved a response."
) )
saved_response = String( saved_response = String(
...@@ -157,6 +159,12 @@ class OpenAssessmentBlock( ...@@ -157,6 +159,12 @@ class OpenAssessmentBlock(
help="Saved response submission for the current user." help="Saved response submission for the current user."
) )
no_peers = Boolean(
default=False,
scope=Scope.user_state,
help="Indicates whether or not there are peers to grade."
)
def get_student_item_dict(self): def get_student_item_dict(self):
"""Create a student_item_dict from our surrounding context. """Create a student_item_dict from our surrounding context.
...@@ -518,3 +526,4 @@ class OpenAssessmentBlock( ...@@ -518,3 +526,4 @@ class OpenAssessmentBlock(
return key.to_deprecated_string() return key.to_deprecated_string()
else: else:
return unicode(key) return unicode(key)
...@@ -203,8 +203,12 @@ class PeerAssessmentMixin(object): ...@@ -203,8 +203,12 @@ class PeerAssessmentMixin(object):
if peer_sub: if peer_sub:
path = 'openassessmentblock/peer/oa_peer_assessment.html' path = 'openassessmentblock/peer/oa_peer_assessment.html'
context_dict["peer_submission"] = peer_sub context_dict["peer_submission"] = peer_sub
# Sets the XBlock boolean to signal to Message that it WAS NOT able to grab a submission
self.no_peers = False
else: else:
path = 'openassessmentblock/peer/oa_peer_waiting.html' path = 'openassessmentblock/peer/oa_peer_waiting.html'
# Sets the XBlock boolean to signal to Message that it WAS able to grab a submission
self.no_peers = True
return path, context_dict return path, context_dict
......
if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.BaseView=function(runtime,element,server){this.runtime=runtime;this.element=element;this.server=server;this.responseView=new OpenAssessment.ResponseView(this.element,this.server,this);this.trainingView=new OpenAssessment.StudentTrainingView(this.element,this.server,this);this.selfView=new OpenAssessment.SelfView(this.element,this.server,this);this.peerView=new OpenAssessment.PeerView(this.element,this.server,this);this.gradeView=new OpenAssessment.GradeView(this.element,this.server,this);this.staffInfoView=new OpenAssessment.StaffInfoView(this.element,this.server,this)};OpenAssessment.BaseView.prototype={scrollToTop:function(){if($.scrollTo instanceof Function){$(window).scrollTo($("#openassessment__steps"),800,{offset:-50})}},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.responseView.load();this.loadAssessmentModules();this.staffInfoView.load()},loadAssessmentModules:function(){this.trainingView.load();this.peerView.load();this.selfView.load();this.gradeView.load()},toggleActionError:function(type,msg){var element=this.element;var container=null;if(type=="save"){container=".response__submission__actions"}else if(type=="submit"||type=="peer"||type=="self"||type=="student-training"){container=".step__actions"}else if(type=="feedback_assess"){container=".submission__feedback__actions"}if(container===null){if(msg!==null){console.log(msg)}}else{var msgHtml=msg===null?"":msg;$(container+" .message__content",element).html("<p>"+msgHtml+"</p>");$(container,element).toggleClass("has--error",msg!==null)}},showLoadError:function(step){var container="#openassessment__"+step;$(container).toggleClass("has--error",true);$(container+" .step__status__value i").removeClass().addClass("ico icon-warning-sign");$(container+" .step__status__value .copy").html(gettext("Unable to Load"))}};function OpenAssessmentBlock(runtime,element){$(function($){var server=new OpenAssessment.Server(runtime,element);var view=new OpenAssessment.BaseView(runtime,element,server);view.load()})}OpenAssessment.StudioView=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 view=this;$(element).find(".openassessment-save-button").click(function(eventData){view.save()});$(element).find(".openassessment-cancel-button").click(function(eventData){view.cancel()})};OpenAssessment.StudioView.prototype={load:function(){var view=this;this.server.loadXml().done(function(xml){view.codeBox.setValue(xml)}).fail(function(msg){view.showError(msg)})},save:function(){var view=this;this.server.checkReleased().done(function(isReleased){if(isReleased){view.confirmPostReleaseUpdate($.proxy(view.updateXml,view))}else{view.updateXml()}}).fail(function(errMsg){view.showError(msg)})},confirmPostReleaseUpdate:function(onConfirm){var msg=gettext("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 view=this;this.server.updateXml(xml).done(function(){view.runtime.notify("save",{state:"end"});view.load()}).fail(function(msg){view.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 view=new OpenAssessment.StudioView(runtime,element,server);view.load()})}OpenAssessment.GradeView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.GradeView.prototype={load:function(){var view=this;var baseView=this.baseView;this.server.render("grade").done(function(html){$("#openassessment__grade",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){baseView.showLoadError("grade",errMsg)})},installHandlers:function(){var sel=$("#openassessment__grade",this.element);this.baseView.setUpCollapseExpand(sel);var view=this;sel.find("#feedback__submit").click(function(eventObject){eventObject.preventDefault();view.submitFeedbackOnAssessment()})},feedbackText:function(text){if(typeof text==="undefined"){return $("#feedback__remarks__value",this.element).val()}else{$("#feedback__remarks__value",this.element).val(text)}},feedbackOptions:function(options){var view=this;if(typeof options==="undefined"){return $.map($(".feedback__overall__value:checked",view.element),function(element,index){return $(element).val()})}else{$(".feedback__overall__value",this.element).prop("checked",false);$.each(options,function(index,opt){$("#feedback__overall__value--"+opt,view.element).prop("checked",true)})}},setHidden:function(sel,hidden){sel.toggleClass("is--hidden",hidden);sel.attr("aria-hidden",hidden?"true":"false")},isHidden:function(sel){return sel.hasClass("is--hidden")&&sel.attr("aria-hidden")=="true"},feedbackState:function(newState){var containerSel=$(".submission__feedback__content",this.element);var instructionsSel=containerSel.find(".submission__feedback__instructions");var fieldsSel=containerSel.find(".submission__feedback__fields");var actionsSel=containerSel.find(".submission__feedback__actions");var transitionSel=containerSel.find(".transition__status");var messageSel=containerSel.find(".message--complete");if(typeof newState==="undefined"){var isSubmitting=containerSel.hasClass("is--transitioning")&&containerSel.hasClass("is--submitting")&&!this.isHidden(transitionSel)&&this.isHidden(messageSel)&&this.isHidden(instructionsSel)&&this.isHidden(fieldsSel)&&this.isHidden(actionsSel);var hasSubmitted=containerSel.hasClass("is--submitted")&&this.isHidden(transitionSel)&&!this.isHidden(messageSel)&&this.isHidden(instructionsSel)&&this.isHidden(fieldsSel)&&this.isHidden(actionsSel);var isOpen=!containerSel.hasClass("is--submitted")&&!containerSel.hasClass("is--transitioning")&&!containerSel.hasClass("is--submitting")&&this.isHidden(transitionSel)&&this.isHidden(messageSel)&&!this.isHidden(instructionsSel)&&!this.isHidden(fieldsSel)&&!this.isHidden(actionsSel);if(isOpen){return"open"}else if(isSubmitting){return"submitting"}else if(hasSubmitted){return"submitted"}else{throw"Invalid feedback state"}}else{if(newState=="open"){containerSel.toggleClass("is--transitioning",false);containerSel.toggleClass("is--submitting",false);containerSel.toggleClass("is--submitted",false);this.setHidden(instructionsSel,false);this.setHidden(fieldsSel,false);this.setHidden(actionsSel,false);this.setHidden(transitionSel,true);this.setHidden(messageSel,true)}else if(newState=="submitting"){containerSel.toggleClass("is--transitioning",true);containerSel.toggleClass("is--submitting",true);containerSel.toggleClass("is--submitted",false);this.setHidden(instructionsSel,true);this.setHidden(fieldsSel,true);this.setHidden(actionsSel,true);this.setHidden(transitionSel,false);this.setHidden(messageSel,true)}else if(newState=="submitted"){containerSel.toggleClass("is--transitioning",false);containerSel.toggleClass("is--submitting",false);containerSel.toggleClass("is--submitted",true);this.setHidden(instructionsSel,true);this.setHidden(fieldsSel,true);this.setHidden(actionsSel,true);this.setHidden(transitionSel,true);this.setHidden(messageSel,false)}}},submitFeedbackOnAssessment:function(){var view=this;var baseView=this.baseView;$("#feedback__submit",this.element).toggleClass("is--disabled",true);view.feedbackState("submitting");this.server.submitFeedbackOnAssessment(this.feedbackText(),this.feedbackOptions()).done(function(){view.feedbackState("submitted")}).fail(function(errMsg){baseView.toggleActionError("feedback_assess",errMsg)})}};OpenAssessment.PeerView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.PeerView.prototype={load:function(){var view=this;this.server.render("peer_assessment").done(function(html){$("#openassessment__peer-assessment",view.element).replaceWith(html);view.installHandlers(false)}).fail(function(errMsg){view.baseView.showLoadError("peer-assessment")})},loadContinuedAssessment:function(){var view=this;this.server.renderContinuedPeer().done(function(html){$("#openassessment__peer-assessment",view.element).replaceWith(html);view.installHandlers(true)}).fail(function(errMsg){view.baseView.showLoadError("peer-assessment")})},installHandlers:function(isContinuedAssessment){var sel=$("#openassessment__peer-assessment",this.element);var view=this;this.baseView.setUpCollapseExpand(sel,$.proxy(view.loadContinuedAssessment,view));var rubricSelector=$("#peer-assessment--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(view.peerSubmitEnabled,view))}sel.find("#peer-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();if(!isContinuedAssessment){view.peerAssess()}else{view.continuedPeerAssess()}})},peerSubmitEnabled:function(enabled){var button=$("#peer-assessment--001__assessment__submit",this.element);if(typeof enabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!enabled)}},peerAssess:function(){var view=this;var baseView=view.baseView;this.peerAssessRequest(function(){view.load();baseView.loadAssessmentModules();baseView.scrollToTop()})},continuedPeerAssess:function(){var view=this;var gradeView=this.baseView.gradeView;var baseView=view.baseView;view.peerAssessRequest(function(){view.loadContinuedAssessment();gradeView.load();baseView.scrollToTop()})},peerAssessRequest:function(successFunction){var view=this;view.baseView.toggleActionError("peer",null);view.peerSubmitEnabled(false);this.server.peerAssess(this.rubric.optionsSelected(),this.rubric.criterionFeedback(),this.overallFeedback()).done(successFunction).fail(function(errMsg){view.baseView.toggleActionError("peer",errMsg);view.peerSubmitEnabled(true)})},overallFeedback:function(overallFeedback){var selector="#assessment__rubric__question--feedback__value";if(typeof overallFeedback==="undefined"){return $(selector,this.element).val()}else{$(selector,this.element).val(overallFeedback)}}};OpenAssessment.ResponseView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.savedResponse="";this.lastChangeTime=Date.now();this.errorOnLastSave=false;this.autoSaveTimerId=null};OpenAssessment.ResponseView.prototype={AUTO_SAVE_POLL_INTERVAL:2e3,AUTO_SAVE_WAIT:3e4,load:function(){var view=this;this.server.render("submission").done(function(html){$("#openassessment__response",view.element).replaceWith(html);view.installHandlers();view.setAutoSaveEnabled(true)}).fail(function(errMsg){view.baseView.showLoadError("response")})},installHandlers:function(){var sel=$("#openassessment__response",this.element);var view=this;this.baseView.setUpCollapseExpand(sel);this.savedResponse=this.response();var handleChange=function(eventData){view.handleResponseChanged()};sel.find("#submission__answer__value").on("change keyup drop paste",handleChange);sel.find("#step--response__submit").click(function(eventObject){eventObject.preventDefault();view.submit()});sel.find("#submission__save").click(function(eventObject){eventObject.preventDefault();view.save()})},setAutoSaveEnabled:function(enabled){if(enabled){if(this.autoSaveTimerId===null){this.autoSaveTimerId=setInterval($.proxy(this.autoSave,this),this.AUTO_SAVE_POLL_INTERVAL)}}else{if(this.autoSaveTimerId!==null){clearInterval(this.autoSaveTimerId)}}},submitEnabled:function(enabled){var sel=$("#step--response__submit",this.element);if(typeof enabled==="undefined"){return!sel.hasClass("is--disabled")}else{sel.toggleClass("is--disabled",!enabled)}},saveEnabled:function(enabled){var sel=$("#submission__save",this.element);if(typeof enabled==="undefined"){return!sel.hasClass("is--disabled")}else{sel.toggleClass("is--disabled",!enabled)}},saveStatus:function(msg){var sel=$("#response__save_status h3",this.element);if(typeof msg==="undefined"){return sel.text()}else{var label=gettext("Status of Your Response");sel.html('<span class="sr">'+label+":"+"</span>\n"+msg)}},unsavedWarningEnabled:function(enabled){if(typeof enabled==="undefined"){return window.onbeforeunload!==null}else{if(enabled){window.onbeforeunload=function(){return"If you leave this page without saving or submitting your response, "+"you'll lose any work you've done on the response."}}else{window.onbeforeunload=null}}},response:function(text){var sel=$("#submission__answer__value",this.element);if(typeof text==="undefined"){return sel.val()}else{sel.val(text)}},responseChanged:function(){var currentResponse=$.trim(this.response());var savedResponse=$.trim(this.savedResponse);return savedResponse!==currentResponse},autoSave:function(){var timeSinceLastChange=Date.now()-this.lastChangeTime;if(this.responseChanged()&&timeSinceLastChange>this.AUTO_SAVE_WAIT&&!this.errorOnLastSave){this.save()}},handleResponseChanged:function(){var isBlank=$.trim(this.response())!=="";this.submitEnabled(isBlank);if(this.responseChanged()){this.saveEnabled(isBlank);this.saveStatus(gettext("This response has not been saved."));this.unsavedWarningEnabled(true)}this.lastChangeTime=Date.now()},save:function(){this.errorOnLastSave=false;this.saveStatus(gettext("Saving..."));this.baseView.toggleActionError("save",null);this.unsavedWarningEnabled(false);var view=this;var savedResponse=this.response();this.server.save(savedResponse).done(function(){view.savedResponse=savedResponse;var currentResponse=view.response();view.submitEnabled(currentResponse!=="");if(currentResponse==savedResponse){view.saveEnabled(false);view.saveStatus(gettext("This response has been saved but not submitted."))}}).fail(function(errMsg){view.saveStatus(gettext("Error"));view.baseView.toggleActionError("save",errMsg);view.errorOnLastSave=true})},submit:function(){this.submitEnabled(false);var view=this;var baseView=this.baseView;this.confirmSubmission().pipe(function(){var submission=$("#submission__answer__value",view.element).val();baseView.toggleActionError("response",null);return view.server.submit(submission)}).done($.proxy(view.moveToNextStep,view)).fail(function(errCode,errMsg){if(errCode=="ENOMULTI"){view.moveToNextStep()}else{if(errMsg){baseView.toggleActionError("submit",errMsg)}view.submitEnabled(true)}})},moveToNextStep:function(){this.load();this.baseView.loadAssessmentModules();this.unsavedWarningEnabled(false)},confirmSubmission:function(){var msg="You're about to submit your response for this assignment. "+"After you submit this response, you can't change it or submit a new response.";return $.Deferred(function(defer){if(confirm(msg)){defer.resolve()}else{defer.reject()}})}};OpenAssessment.Rubric=function(element){this.element=element};OpenAssessment.Rubric.prototype={criterionFeedback:function(criterionFeedback){var selector="textarea.answer__value";var feedback={};$(selector,this.element).each(function(index,sel){if(typeof criterionFeedback!=="undefined"){$(sel).val(criterionFeedback[sel.name]);feedback[sel.name]=criterionFeedback[sel.name]}else{feedback[sel.name]=$(sel).val()}});return feedback},optionsSelected:function(optionsSelected){var selector="input[type=radio]";if(typeof optionsSelected==="undefined"){var options={};$(selector+":checked",this.element).each(function(index,sel){options[sel.name]=sel.value});return options}else{$(selector,this.element).prop("checked",false);$(selector,this.element).each(function(index,sel){if(optionsSelected.hasOwnProperty(sel.name)){if(sel.value==optionsSelected[sel.name]){$(sel).prop("checked",true)}}})}},canSubmitCallback:function(callback){$(this.element).change(function(){var numChecked=$("input[type=radio]:checked",this).length;var numAvailable=$(".field--radio.assessment__rubric__question",this).length;var canSubmit=numChecked==numAvailable;callback(canSubmit)})},showCorrections:function(corrections){var selector="input[type=radio]";var hasErrors=false;$(selector,this.element).each(function(index,sel){var listItem=$(sel).parents(".assessment__rubric__question");if(corrections.hasOwnProperty(sel.name)){hasErrors=true;listItem.find(".message--incorrect").removeClass("is--hidden");listItem.find(".message--correct").addClass("is--hidden")}else{listItem.find(".message--correct").removeClass("is--hidden");listItem.find(".message--incorrect").addClass("is--hidden")}});return hasErrors}};OpenAssessment.SelfView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.SelfView.prototype={load:function(){var view=this;this.server.render("self_assessment").done(function(html){$("#openassessment__self-assessment",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.showLoadError("self-assessment")})},installHandlers:function(){var view=this;var sel=$("#openassessment__self-assessment",view.element);this.baseView.setUpCollapseExpand(sel);var rubricSelector=$("#self-assessment--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(this.selfSubmitEnabled,this))}sel.find("#self-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();view.selfAssess()})},selfSubmitEnabled:function(enabled){var button=$("#self-assessment--001__assessment__submit",this.element);if(typeof enabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!enabled)}},selfAssess:function(){var view=this;var baseView=this.baseView;baseView.toggleActionError("self",null);view.selfSubmitEnabled(false);var options=this.rubric.optionsSelected();this.server.selfAssess(options).done(function(){baseView.loadAssessmentModules();baseView.scrollToTop()}).fail(function(errMsg){baseView.toggleActionError("self",errMsg);view.selfSubmitEnabled(true)})}};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,[gettext("This section could not be loaded.")])})}).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,[gettext("This section could not be loaded.")])})}).promise()},studentInfo:function(student_id){var url=this.url("render_student_info");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{student_id:student_id}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).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",gettext("This response could not be submitted.")])})}).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,[gettext("This response could not be saved.")])})}).promise()},submitFeedbackOnAssessment:function(text,options){var url=this.url("submit_feedback");var payload=JSON.stringify({feedback_text:text,feedback_options:options});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,[gettext("This feedback could not be submitted.")])})}).promise()},peerAssess:function(optionsSelected,criterionFeedback,overallFeedback){var url=this.url("peer_assess");var payload=JSON.stringify({options_selected:optionsSelected,criterion_feedback:criterionFeedback,overall_feedback:overallFeedback});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,[gettext("This assessment could not be submitted.")])})}).promise()},selfAssess:function(optionsSelected){var url=this.url("self_assess");var payload=JSON.stringify({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,[gettext("This assessment could not be submitted.")])})})},trainingAssess:function(optionsSelected){var url=this.url("training_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.corrections])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},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,[gettext("This problem could not be loaded.")])})}).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,[gettext("This problem could not be saved.")])})}).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,[gettext("The server could not be contacted.")])})}).promise()}};if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.StaffInfoView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.StaffInfoView.prototype={load:function(){var view=this;this.server.render("staff_info").done(function(html){$("#openassessment__staff-info",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.baseView.showLoadError("staff_info")})},loadStudentInfo:function(){var view=this;var sel=$("#openassessment__staff-info",this.element);var student_id=sel.find("#openassessment__student_id").val();this.server.studentInfo(student_id).done(function(html){$("#openassessment__student-info",view.element).replaceWith(html)}).fail(function(errMsg){view.showLoadError("student_info")})},installHandlers:function(){var sel=$("#openassessment__staff-info",this.element);var view=this;if(sel.length<=0){return}this.baseView.setUpCollapseExpand(sel,function(){});sel.find("#openassessment_student_info_form").submit(function(eventObject){eventObject.preventDefault();view.loadStudentInfo()});sel.find("#submit_student_id").click(function(eventObject){eventObject.preventDefault();view.loadStudentInfo()})}};OpenAssessment.StudentTrainingView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.StudentTrainingView.prototype={load:function(){var view=this;this.server.render("student_training").done(function(html){$("#openassessment__student-training",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.baseView.showLoadError("student-training")})},installHandlers:function(){var sel=$("#openassessment__student-training",this.element);var view=this;this.baseView.setUpCollapseExpand(sel);var rubricSelector=$("#student-training--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(this.assessButtonEnabled,this))}sel.find("#student-training--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();view.assess()})},assess:function(){this.assessButtonEnabled(false);var options={};if(this.rubric!==null){options=this.rubric.optionsSelected()}var view=this;var baseView=this.baseView;this.server.trainingAssess(options).done(function(corrections){var incorrect=$("#openassessment__student-training--incorrect",this.element);var instructions=$("#openassessment__student-training--instructions",this.element);if(!view.rubric.showCorrections(corrections)){baseView.loadAssessmentModules();incorrect.addClass("is--hidden");instructions.removeClass("is--hidden")}else{instructions.addClass("is--hidden");incorrect.removeClass("is--hidden")}baseView.scrollToTop()}).fail(function(errMsg){baseView.toggleActionError("student-training",errMsg);view.assessButtonEnabled(true)})},assessButtonEnabled:function(isEnabled){var button=$("#student-training--001__assessment__submit",this.element);if(typeof isEnabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!isEnabled)}}}; if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.BaseView=function(runtime,element,server){this.runtime=runtime;this.element=element;this.server=server;this.responseView=new OpenAssessment.ResponseView(this.element,this.server,this);this.trainingView=new OpenAssessment.StudentTrainingView(this.element,this.server,this);this.selfView=new OpenAssessment.SelfView(this.element,this.server,this);this.peerView=new OpenAssessment.PeerView(this.element,this.server,this);this.gradeView=new OpenAssessment.GradeView(this.element,this.server,this);this.messageView=new OpenAssessment.MessageView(this.element,this.server,this);this.staffInfoView=new OpenAssessment.StaffInfoView(this.element,this.server,this)};OpenAssessment.BaseView.prototype={scrollToTop:function(){if($.scrollTo instanceof Function){$(window).scrollTo($("#openassessment__steps"),800,{offset:-50})}},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.responseView.load();this.loadAssessmentModules();this.staffInfoView.load()},loadAssessmentModules:function(){this.trainingView.load();this.peerView.load();this.selfView.load();this.gradeView.load()},loadMessageView:function(){this.messageView.load()},toggleActionError:function(type,msg){var element=this.element;var container=null;if(type=="save"){container=".response__submission__actions"}else if(type=="submit"||type=="peer"||type=="self"||type=="student-training"){container=".step__actions"}else if(type=="feedback_assess"){container=".submission__feedback__actions"}if(container===null){if(msg!==null){console.log(msg)}}else{var msgHtml=msg===null?"":msg;$(container+" .message__content",element).html("<p>"+msgHtml+"</p>");$(container,element).toggleClass("has--error",msg!==null)}},showLoadError:function(step){var container="#openassessment__"+step;$(container).toggleClass("has--error",true);$(container+" .step__status__value i").removeClass().addClass("ico icon-warning-sign");$(container+" .step__status__value .copy").html(gettext("Unable to Load"))}};function OpenAssessmentBlock(runtime,element){$(function($){var server=new OpenAssessment.Server(runtime,element);var view=new OpenAssessment.BaseView(runtime,element,server);view.load()})}OpenAssessment.StudioView=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 view=this;$(element).find(".openassessment-save-button").click(function(eventData){view.save()});$(element).find(".openassessment-cancel-button").click(function(eventData){view.cancel()})};OpenAssessment.StudioView.prototype={load:function(){var view=this;this.server.loadXml().done(function(xml){view.codeBox.setValue(xml)}).fail(function(msg){view.showError(msg)})},save:function(){var view=this;this.server.checkReleased().done(function(isReleased){if(isReleased){view.confirmPostReleaseUpdate($.proxy(view.updateXml,view))}else{view.updateXml()}}).fail(function(errMsg){view.showError(msg)})},confirmPostReleaseUpdate:function(onConfirm){var msg=gettext("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 view=this;this.server.updateXml(xml).done(function(){view.runtime.notify("save",{state:"end"});view.load()}).fail(function(msg){view.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 view=new OpenAssessment.StudioView(runtime,element,server);view.load()})}OpenAssessment.GradeView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.GradeView.prototype={load:function(){var view=this;var baseView=this.baseView;this.server.render("grade").done(function(html){$("#openassessment__grade",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){baseView.showLoadError("grade",errMsg)})},installHandlers:function(){var sel=$("#openassessment__grade",this.element);this.baseView.setUpCollapseExpand(sel);var view=this;sel.find("#feedback__submit").click(function(eventObject){eventObject.preventDefault();view.submitFeedbackOnAssessment()})},feedbackText:function(text){if(typeof text==="undefined"){return $("#feedback__remarks__value",this.element).val()}else{$("#feedback__remarks__value",this.element).val(text)}},feedbackOptions:function(options){var view=this;if(typeof options==="undefined"){return $.map($(".feedback__overall__value:checked",view.element),function(element,index){return $(element).val()})}else{$(".feedback__overall__value",this.element).prop("checked",false);$.each(options,function(index,opt){$("#feedback__overall__value--"+opt,view.element).prop("checked",true)})}},setHidden:function(sel,hidden){sel.toggleClass("is--hidden",hidden);sel.attr("aria-hidden",hidden?"true":"false")},isHidden:function(sel){return sel.hasClass("is--hidden")&&sel.attr("aria-hidden")=="true"},feedbackState:function(newState){var containerSel=$(".submission__feedback__content",this.element);var instructionsSel=containerSel.find(".submission__feedback__instructions");var fieldsSel=containerSel.find(".submission__feedback__fields");var actionsSel=containerSel.find(".submission__feedback__actions");var transitionSel=containerSel.find(".transition__status");var messageSel=containerSel.find(".message--complete");if(typeof newState==="undefined"){var isSubmitting=containerSel.hasClass("is--transitioning")&&containerSel.hasClass("is--submitting")&&!this.isHidden(transitionSel)&&this.isHidden(messageSel)&&this.isHidden(instructionsSel)&&this.isHidden(fieldsSel)&&this.isHidden(actionsSel);var hasSubmitted=containerSel.hasClass("is--submitted")&&this.isHidden(transitionSel)&&!this.isHidden(messageSel)&&this.isHidden(instructionsSel)&&this.isHidden(fieldsSel)&&this.isHidden(actionsSel);var isOpen=!containerSel.hasClass("is--submitted")&&!containerSel.hasClass("is--transitioning")&&!containerSel.hasClass("is--submitting")&&this.isHidden(transitionSel)&&this.isHidden(messageSel)&&!this.isHidden(instructionsSel)&&!this.isHidden(fieldsSel)&&!this.isHidden(actionsSel);if(isOpen){return"open"}else if(isSubmitting){return"submitting"}else if(hasSubmitted){return"submitted"}else{throw"Invalid feedback state"}}else{if(newState=="open"){containerSel.toggleClass("is--transitioning",false);containerSel.toggleClass("is--submitting",false);containerSel.toggleClass("is--submitted",false);this.setHidden(instructionsSel,false);this.setHidden(fieldsSel,false);this.setHidden(actionsSel,false);this.setHidden(transitionSel,true);this.setHidden(messageSel,true)}else if(newState=="submitting"){containerSel.toggleClass("is--transitioning",true);containerSel.toggleClass("is--submitting",true);containerSel.toggleClass("is--submitted",false);this.setHidden(instructionsSel,true);this.setHidden(fieldsSel,true);this.setHidden(actionsSel,true);this.setHidden(transitionSel,false);this.setHidden(messageSel,true)}else if(newState=="submitted"){containerSel.toggleClass("is--transitioning",false);containerSel.toggleClass("is--submitting",false);containerSel.toggleClass("is--submitted",true);this.setHidden(instructionsSel,true);this.setHidden(fieldsSel,true);this.setHidden(actionsSel,true);this.setHidden(transitionSel,true);this.setHidden(messageSel,false)}}},submitFeedbackOnAssessment:function(){var view=this;var baseView=this.baseView;$("#feedback__submit",this.element).toggleClass("is--disabled",true);view.feedbackState("submitting");this.server.submitFeedbackOnAssessment(this.feedbackText(),this.feedbackOptions()).done(function(){view.feedbackState("submitted")}).fail(function(errMsg){baseView.toggleActionError("feedback_assess",errMsg)})}};OpenAssessment.MessageView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.MessageView.prototype={load:function(){var view=this;var baseView=this.baseView;this.server.render("message").done(function(html){$("#openassessment__message",view.element).replaceWith(html)}).fail(function(errMsg){baseView.showLoadError("message",errMsg)})}};OpenAssessment.PeerView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.PeerView.prototype={load:function(){var view=this;this.server.render("peer_assessment").done(function(html){$("#openassessment__peer-assessment",view.element).replaceWith(html);view.installHandlers(false)}).fail(function(errMsg){view.baseView.showLoadError("peer-assessment")});view.baseView.loadMessageView()},loadContinuedAssessment:function(){var view=this;this.server.renderContinuedPeer().done(function(html){$("#openassessment__peer-assessment",view.element).replaceWith(html);view.installHandlers(true)}).fail(function(errMsg){view.baseView.showLoadError("peer-assessment")})},installHandlers:function(isContinuedAssessment){var sel=$("#openassessment__peer-assessment",this.element);var view=this;this.baseView.setUpCollapseExpand(sel,$.proxy(view.loadContinuedAssessment,view));var rubricSelector=$("#peer-assessment--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(view.peerSubmitEnabled,view))}sel.find("#peer-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();if(!isContinuedAssessment){view.peerAssess()}else{view.continuedPeerAssess()}})},peerSubmitEnabled:function(enabled){var button=$("#peer-assessment--001__assessment__submit",this.element);if(typeof enabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!enabled)}},peerAssess:function(){var view=this;var baseView=view.baseView;this.peerAssessRequest(function(){view.load();baseView.loadAssessmentModules();baseView.scrollToTop()})},continuedPeerAssess:function(){var view=this;var gradeView=this.baseView.gradeView;var baseView=view.baseView;view.peerAssessRequest(function(){view.loadContinuedAssessment();gradeView.load();baseView.scrollToTop()})},peerAssessRequest:function(successFunction){var view=this;view.baseView.toggleActionError("peer",null);view.peerSubmitEnabled(false);this.server.peerAssess(this.rubric.optionsSelected(),this.rubric.criterionFeedback(),this.overallFeedback()).done(successFunction).fail(function(errMsg){view.baseView.toggleActionError("peer",errMsg);view.peerSubmitEnabled(true)})},overallFeedback:function(overallFeedback){var selector="#assessment__rubric__question--feedback__value";if(typeof overallFeedback==="undefined"){return $(selector,this.element).val()}else{$(selector,this.element).val(overallFeedback)}}};OpenAssessment.ResponseView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.savedResponse="";this.lastChangeTime=Date.now();this.errorOnLastSave=false;this.autoSaveTimerId=null};OpenAssessment.ResponseView.prototype={AUTO_SAVE_POLL_INTERVAL:2e3,AUTO_SAVE_WAIT:3e4,load:function(){var view=this;this.server.render("submission").done(function(html){$("#openassessment__response",view.element).replaceWith(html);view.installHandlers();view.setAutoSaveEnabled(true)}).fail(function(errMsg){view.baseView.showLoadError("response")})},installHandlers:function(){var sel=$("#openassessment__response",this.element);var view=this;this.baseView.setUpCollapseExpand(sel);this.savedResponse=this.response();var handleChange=function(eventData){view.handleResponseChanged()};sel.find("#submission__answer__value").on("change keyup drop paste",handleChange);sel.find("#step--response__submit").click(function(eventObject){eventObject.preventDefault();view.submit()});sel.find("#submission__save").click(function(eventObject){eventObject.preventDefault();view.save()})},setAutoSaveEnabled:function(enabled){if(enabled){if(this.autoSaveTimerId===null){this.autoSaveTimerId=setInterval($.proxy(this.autoSave,this),this.AUTO_SAVE_POLL_INTERVAL)}}else{if(this.autoSaveTimerId!==null){clearInterval(this.autoSaveTimerId)}}},submitEnabled:function(enabled){var sel=$("#step--response__submit",this.element);if(typeof enabled==="undefined"){return!sel.hasClass("is--disabled")}else{sel.toggleClass("is--disabled",!enabled)}},saveEnabled:function(enabled){var sel=$("#submission__save",this.element);if(typeof enabled==="undefined"){return!sel.hasClass("is--disabled")}else{sel.toggleClass("is--disabled",!enabled)}},saveStatus:function(msg){var sel=$("#response__save_status h3",this.element);if(typeof msg==="undefined"){return sel.text()}else{var label=gettext("Status of Your Response");sel.html('<span class="sr">'+label+":"+"</span>\n"+msg)}},unsavedWarningEnabled:function(enabled){if(typeof enabled==="undefined"){return window.onbeforeunload!==null}else{if(enabled){window.onbeforeunload=function(){return"If you leave this page without saving or submitting your response, "+"you'll lose any work you've done on the response."}}else{window.onbeforeunload=null}}},response:function(text){var sel=$("#submission__answer__value",this.element);if(typeof text==="undefined"){return sel.val()}else{sel.val(text)}},responseChanged:function(){var currentResponse=$.trim(this.response());var savedResponse=$.trim(this.savedResponse);return savedResponse!==currentResponse},autoSave:function(){var timeSinceLastChange=Date.now()-this.lastChangeTime;if(this.responseChanged()&&timeSinceLastChange>this.AUTO_SAVE_WAIT&&!this.errorOnLastSave){this.save()}},handleResponseChanged:function(){var isBlank=$.trim(this.response())!=="";this.submitEnabled(isBlank);if(this.responseChanged()){this.saveEnabled(isBlank);this.saveStatus(gettext("This response has not been saved."));this.unsavedWarningEnabled(true)}this.lastChangeTime=Date.now()},save:function(){this.errorOnLastSave=false;this.saveStatus(gettext("Saving..."));this.baseView.toggleActionError("save",null);this.unsavedWarningEnabled(false);var view=this;var savedResponse=this.response();this.server.save(savedResponse).done(function(){view.savedResponse=savedResponse;var currentResponse=view.response();view.submitEnabled(currentResponse!=="");if(currentResponse==savedResponse){view.saveEnabled(false);view.saveStatus(gettext("This response has been saved but not submitted."))}}).fail(function(errMsg){view.saveStatus(gettext("Error"));view.baseView.toggleActionError("save",errMsg);view.errorOnLastSave=true})},submit:function(){this.submitEnabled(false);var view=this;var baseView=this.baseView;this.confirmSubmission().pipe(function(){var submission=$("#submission__answer__value",view.element).val();baseView.toggleActionError("response",null);return view.server.submit(submission)}).done($.proxy(view.moveToNextStep,view)).fail(function(errCode,errMsg){if(errCode=="ENOMULTI"){view.moveToNextStep()}else{if(errMsg){baseView.toggleActionError("submit",errMsg)}view.submitEnabled(true)}})},moveToNextStep:function(){this.load();this.baseView.loadAssessmentModules();this.unsavedWarningEnabled(false)},confirmSubmission:function(){var msg="You're about to submit your response for this assignment. "+"After you submit this response, you can't change it or submit a new response.";return $.Deferred(function(defer){if(confirm(msg)){defer.resolve()}else{defer.reject()}})}};OpenAssessment.Rubric=function(element){this.element=element};OpenAssessment.Rubric.prototype={criterionFeedback:function(criterionFeedback){var selector="textarea.answer__value";var feedback={};$(selector,this.element).each(function(index,sel){if(typeof criterionFeedback!=="undefined"){$(sel).val(criterionFeedback[sel.name]);feedback[sel.name]=criterionFeedback[sel.name]}else{feedback[sel.name]=$(sel).val()}});return feedback},optionsSelected:function(optionsSelected){var selector="input[type=radio]";if(typeof optionsSelected==="undefined"){var options={};$(selector+":checked",this.element).each(function(index,sel){options[sel.name]=sel.value});return options}else{$(selector,this.element).prop("checked",false);$(selector,this.element).each(function(index,sel){if(optionsSelected.hasOwnProperty(sel.name)){if(sel.value==optionsSelected[sel.name]){$(sel).prop("checked",true)}}})}},canSubmitCallback:function(callback){$(this.element).change(function(){var numChecked=$("input[type=radio]:checked",this).length;var numAvailable=$(".field--radio.assessment__rubric__question",this).length;var canSubmit=numChecked==numAvailable;callback(canSubmit)})},showCorrections:function(corrections){var selector="input[type=radio]";var hasErrors=false;$(selector,this.element).each(function(index,sel){var listItem=$(sel).parents(".assessment__rubric__question");if(corrections.hasOwnProperty(sel.name)){hasErrors=true;listItem.find(".message--incorrect").removeClass("is--hidden");listItem.find(".message--correct").addClass("is--hidden")}else{listItem.find(".message--correct").removeClass("is--hidden");listItem.find(".message--incorrect").addClass("is--hidden")}});return hasErrors}};OpenAssessment.SelfView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.SelfView.prototype={load:function(){var view=this;this.server.render("self_assessment").done(function(html){$("#openassessment__self-assessment",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.showLoadError("self-assessment")})},installHandlers:function(){var view=this;var sel=$("#openassessment__self-assessment",view.element);this.baseView.setUpCollapseExpand(sel);var rubricSelector=$("#self-assessment--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(this.selfSubmitEnabled,this))}sel.find("#self-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();view.selfAssess()})},selfSubmitEnabled:function(enabled){var button=$("#self-assessment--001__assessment__submit",this.element);if(typeof enabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!enabled)}},selfAssess:function(){var view=this;var baseView=this.baseView;baseView.toggleActionError("self",null);view.selfSubmitEnabled(false);var options=this.rubric.optionsSelected();this.server.selfAssess(options).done(function(){baseView.loadAssessmentModules();baseView.scrollToTop()}).fail(function(errMsg){baseView.toggleActionError("self",errMsg);view.selfSubmitEnabled(true)})}};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,[gettext("This section could not be loaded.")])})}).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,[gettext("This section could not be loaded.")])})}).promise()},studentInfo:function(student_id){var url=this.url("render_student_info");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{student_id:student_id}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).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",gettext("This response could not be submitted.")])})}).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,[gettext("This response could not be saved.")])})}).promise()},submitFeedbackOnAssessment:function(text,options){var url=this.url("submit_feedback");var payload=JSON.stringify({feedback_text:text,feedback_options:options});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,[gettext("This feedback could not be submitted.")])})}).promise()},peerAssess:function(optionsSelected,criterionFeedback,overallFeedback){var url=this.url("peer_assess");var payload=JSON.stringify({options_selected:optionsSelected,criterion_feedback:criterionFeedback,overall_feedback:overallFeedback});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,[gettext("This assessment could not be submitted.")])})}).promise()},selfAssess:function(optionsSelected){var url=this.url("self_assess");var payload=JSON.stringify({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,[gettext("This assessment could not be submitted.")])})})},trainingAssess:function(optionsSelected){var url=this.url("training_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.corrections])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},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,[gettext("This problem could not be loaded.")])})}).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,[gettext("This problem could not be saved.")])})}).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,[gettext("The server could not be contacted.")])})}).promise()}};if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.StaffInfoView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.StaffInfoView.prototype={load:function(){var view=this;this.server.render("staff_info").done(function(html){$("#openassessment__staff-info",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.baseView.showLoadError("staff_info")})},loadStudentInfo:function(){var view=this;var sel=$("#openassessment__staff-info",this.element);var student_id=sel.find("#openassessment__student_id").val();this.server.studentInfo(student_id).done(function(html){$("#openassessment__student-info",view.element).replaceWith(html)}).fail(function(errMsg){view.showLoadError("student_info")})},installHandlers:function(){var sel=$("#openassessment__staff-info",this.element);var view=this;if(sel.length<=0){return}this.baseView.setUpCollapseExpand(sel,function(){});sel.find("#openassessment_student_info_form").submit(function(eventObject){eventObject.preventDefault();view.loadStudentInfo()});sel.find("#submit_student_id").click(function(eventObject){eventObject.preventDefault();view.loadStudentInfo()})}};OpenAssessment.StudentTrainingView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.StudentTrainingView.prototype={load:function(){var view=this;this.server.render("student_training").done(function(html){$("#openassessment__student-training",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.baseView.showLoadError("student-training")})},installHandlers:function(){var sel=$("#openassessment__student-training",this.element);var view=this;this.baseView.setUpCollapseExpand(sel);var rubricSelector=$("#student-training--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(this.assessButtonEnabled,this))}sel.find("#student-training--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();view.assess()})},assess:function(){this.assessButtonEnabled(false);var options={};if(this.rubric!==null){options=this.rubric.optionsSelected()}var view=this;var baseView=this.baseView;this.server.trainingAssess(options).done(function(corrections){var incorrect=$("#openassessment__student-training--incorrect",this.element);var instructions=$("#openassessment__student-training--instructions",this.element);if(!view.rubric.showCorrections(corrections)){baseView.loadAssessmentModules();incorrect.addClass("is--hidden");instructions.removeClass("is--hidden")}else{instructions.addClass("is--hidden");incorrect.removeClass("is--hidden")}baseView.scrollToTop()}).fail(function(errMsg){baseView.toggleActionError("student-training",errMsg);view.assessButtonEnabled(true)})},assessButtonEnabled:function(isEnabled){var button=$("#student-training--001__assessment__submit",this.element);if(typeof isEnabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!isEnabled)}}};
\ No newline at end of file \ No newline at end of file
...@@ -28,6 +28,7 @@ describe("OpenAssessment.PeerView", function() { ...@@ -28,6 +28,7 @@ describe("OpenAssessment.PeerView", function() {
this.setUpCollapseExpand = function(sel) {}; this.setUpCollapseExpand = function(sel) {};
this.scrollToTop = function() {}; this.scrollToTop = function() {};
this.loadAssessmentModules = function() {}; this.loadAssessmentModules = function() {};
this.loadMessageView = function() {};
}; };
// Stubs // Stubs
......
...@@ -19,7 +19,7 @@ OpenAssessment.BaseView = function(runtime, element, server) { ...@@ -19,7 +19,7 @@ OpenAssessment.BaseView = function(runtime, element, server) {
this.selfView = new OpenAssessment.SelfView(this.element, this.server, this); this.selfView = new OpenAssessment.SelfView(this.element, this.server, this);
this.peerView = new OpenAssessment.PeerView(this.element, this.server, this); this.peerView = new OpenAssessment.PeerView(this.element, this.server, this);
this.gradeView = new OpenAssessment.GradeView(this.element, this.server, this); this.gradeView = new OpenAssessment.GradeView(this.element, this.server, this);
this.messageView = new OpenAssessment.MessageView(this.element, this.server, this);
// Staff only information about student progress. // Staff only information about student progress.
this.staffInfoView = new OpenAssessment.StaffInfoView(this.element, this.server, this); this.staffInfoView = new OpenAssessment.StaffInfoView(this.element, this.server, this);
}; };
...@@ -80,6 +80,26 @@ OpenAssessment.BaseView.prototype = { ...@@ -80,6 +80,26 @@ OpenAssessment.BaseView.prototype = {
this.peerView.load(); this.peerView.load();
this.selfView.load(); this.selfView.load();
this.gradeView.load(); this.gradeView.load();
/**
this.messageView.load() is intentionally omitted.
Because of the asynchronous loading, there is no way to tell (from the perspective of the
messageView) whether or not the peer view was able to grab an assessment to assess. Any
asynchronous strategy would run into a race condition based around this problem at some
point. Instead, we created a field in the XBlock called no_peers, which is set by the
Peer XBlock Handler, and which is examined by the Message XBlock Handler.
To Avoid rendering the message more than one time per update/load (and avoiding all comp-
lications that that would likely induce), we chose to load the method view only after
the peer view has been loaded. This is achieved by having the peer view call to render
the message view after rendering itself but before exiting its load method.
*/
},
/**
Refresh the message only (called by PeerView to update and avoid race condition)
**/
loadMessageView: function() {
this.messageView.load();
}, },
/** /**
......
/**
Interface for Message banner.
Args:
element (DOM element): The DOM element representing the XBlock.
server (OpenAssessment.Server): The interface to the XBlock server.
baseView (OpenAssessment.BaseView): Container view.
Returns:
OpenAssessment.ResponseView
**/
OpenAssessment.MessageView = function(element, server, baseView) {
this.element = element;
this.server = server;
this.baseView = baseView;
};
OpenAssessment.MessageView.prototype = {
/**
Loads the message view.
**/
load: function() {
var view = this;
var baseView = this.baseView;
this.server.render('message').done(
function(html) {
//Load the HTML
$('#openassessment__message', view.element).replaceWith(html);
}
).fail(function(errMsg) {
baseView.showLoadError('message', errMsg);
});
}
}
\ No newline at end of file
...@@ -33,6 +33,9 @@ OpenAssessment.PeerView.prototype = { ...@@ -33,6 +33,9 @@ OpenAssessment.PeerView.prototype = {
).fail(function(errMsg) { ).fail(function(errMsg) {
view.baseView.showLoadError('peer-assessment'); view.baseView.showLoadError('peer-assessment');
}); });
// Called to update Messagview with info on whether or not it was able to grab a submission
// See detailed explanation/Methodology in oa_base.loadAssessmentModules
view.baseView.loadMessageView();
}, },
/** /**
......
<openassessment submission_due="2099-01-23">
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>𝓒𝓸𝓷𝓬𝓲𝓼𝓮</name>
<prompt>How concise is it?</prompt>
<option points="3">
<name>ﻉซƈﻉɭɭﻉกՇ</name>
<explanation>Extremely concise</explanation>
</option>
<option points="2">
<name>Ġööḋ</name>
<explanation>Concise</explanation>
</option>
<option points="1">
<name>ק๏๏г</name>
<explanation>Wordy</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>How well-formed is it?</prompt>
<option points="3">
<name>Good</name>
<explanation>Good</explanation>
</option>
<option points="2">
<name>Fair</name>
<explanation>Fair</explanation>
</option>
<option points="1">
<name>Poor</name>
<explanation>Poor</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="1" must_be_graded_by="1" due="2099-05-23"/>
<assessment name="self-assessment" due="2099-05-23"/>
</assessments>
</openassessment>
<openassessment>
<title>Only Self Assessment</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>Concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>Neal Stephenson explanation</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>HP Lovecraft explanation</explanation>
</option>
<option points="3">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="4">
<name>Neal Stephenson (early)</name>
<explanation>Neal Stephenson (early) explanation</explanation>
</option>
<option points="5">
<name>Earnest Hemingway</name>
<explanation>Earnest Hemingway</explanation>
</option>
</criterion>
<criterion>
<name>Clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Yogi Berra</name>
<explanation>Yogi Berra explanation</explanation>
</option>
<option points="1">
<name>Hunter S. Thompson</name>
<explanation>Hunter S. Thompson explanation</explanation>
</option>
<option points="2">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="3">
<name>Isaac Asimov</name>
<explanation>Isaac Asimov explanation</explanation>
</option>
<option points="10">
<name>Spock</name>
<explanation>Spock explanation</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>lolcats</name>
<explanation>lolcats explanation</explanation>
</option>
<option points="1">
<name>Facebook</name>
<explanation>Facebook explanation</explanation>
</option>
<option points="2">
<name>Reddit</name>
<explanation>Reddit explanation</explanation>
</option>
<option points="3">
<name>metafilter</name>
<explanation>metafilter explanation</explanation>
</option>
<option points="4">
<name>Usenet, 1996</name>
<explanation>Usenet, 1996 explanation</explanation>
</option>
<option points="5">
<name>The Elements of Style</name>
<explanation>The Elements of Style explanation</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="self-assessment" />
</assessments>
</openassessment>
<openassessment>
<title>Open Assessment Test</title>
<prompt>
Given the state of the world today, what do you think should be done to
combat poverty? Please answer in a short essay of 200-300 words.
</prompt>
<rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion>
<name>Concise</name>
<prompt>How concise is it?</prompt>
<option points="0">
<name>Neal Stephenson (late)</name>
<explanation>Neal Stephenson explanation</explanation>
</option>
<option points="1">
<name>HP Lovecraft</name>
<explanation>HP Lovecraft explanation</explanation>
</option>
<option points="3">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="4">
<name>Neal Stephenson (early)</name>
<explanation>Neal Stephenson (early) explanation</explanation>
</option>
<option points="5">
<name>Earnest Hemingway</name>
<explanation>Earnest Hemingway</explanation>
</option>
</criterion>
<criterion>
<name>Clear-headed</name>
<prompt>How clear is the thinking?</prompt>
<option points="0">
<name>Yogi Berra</name>
<explanation>Yogi Berra explanation</explanation>
</option>
<option points="1">
<name>Hunter S. Thompson</name>
<explanation>Hunter S. Thompson explanation</explanation>
</option>
<option points="2">
<name>Robert Heinlein</name>
<explanation>Robert Heinlein explanation</explanation>
</option>
<option points="3">
<name>Isaac Asimov</name>
<explanation>Isaac Asimov explanation</explanation>
</option>
<option points="10">
<name>Spock</name>
<explanation>Spock explanation</explanation>
</option>
</criterion>
<criterion>
<name>Form</name>
<prompt>Lastly, how is its form? Punctuation, grammar, and spelling all count.</prompt>
<option points="0">
<name>lolcats</name>
<explanation>lolcats explanation</explanation>
</option>
<option points="1">
<name>Facebook</name>
<explanation>Facebook explanation</explanation>
</option>
<option points="2">
<name>Reddit</name>
<explanation>Reddit explanation</explanation>
</option>
<option points="3">
<name>metafilter</name>
<explanation>metafilter explanation</explanation>
</option>
<option points="4">
<name>Usenet, 1996</name>
<explanation>Usenet, 1996 explanation</explanation>
</option>
<option points="5">
<name>The Elements of Style</name>
<explanation>The Elements of Style explanation</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="peer-assessment" must_grade="5" must_be_graded_by="3" />
</assessments>
</openassessment>
<openassessment>
<title>Student training test</title>
<prompt>Test prompt</prompt>
<rubric>
<prompt>Test rubric prompt</prompt>
<criterion>
<name>Vocabulary</name>
<prompt>How varied is the vocabulary?</prompt>
<option points="0">
<name>Poor</name>
<explanation>Poor job</explanation>
</option>
<option points="1">
<name>Good</name>
<explanation>Good job</explanation>
</option>
<option points="3">
<name>Excellent</name>
<explanation>Excellent job</explanation>
</option>
</criterion>
<criterion>
<name>Grammar</name>
<prompt>How correct is the grammar?</prompt>
<option points="0">
<name>Poor</name>
<explanation>Poor job</explanation>
</option>
<option points="1">
<name>Good</name>
<explanation>Good job</explanation>
</option>
<option points="3">
<name>Excellent</name>
<explanation>Excellent job</explanation>
</option>
</criterion>
</rubric>
<assessments>
<assessment name="student-training">
<example>
<answer>This is my answer.</answer>
<select criterion="Vocabulary" option="Good" />
<select criterion="Grammar" option="Excellent" />
</example>
<example>
<answer>тєѕт αηѕωєя</answer>
<select criterion="Vocabulary" option="Excellent" />
<select criterion="Grammar" option="Poor" />
</example>
</assessment>
<assessment name="peer-assessment" must_grade="5" must_be_graded_by="3" />
<assessment name="self-assessment" />
</assessments>
</openassessment>
# -*- coding: utf-8 -*-
"""
Tests for message handlers in Open Assessment XBlock.
"""
import mock
import pytz
import datetime as dt
from openassessment.xblock.openassessmentblock import OpenAssessmentBlock
from .base import XBlockHandlerTestCase, scenario
class TestMessageRender(XBlockHandlerTestCase):
"""
Tests for the Message XBlock Handler
"""
# Sets up all of the pre-set dates. Uses base day of today in order to allow
# comparison regardless of true date. For this reason, the dates in the XML are
# ignored and irrelevant (because we patch is_closed)
TODAY = dt.date.today()
TODAY = dt.datetime(TODAY.year, TODAY.month, TODAY.day, 0, 0, 0, tzinfo=pytz.utc)
TOMORROW = TODAY + dt.timedelta(days=1)
FUTURE = TODAY + dt.timedelta(days=10)
FAR_FUTURE = TODAY + dt.timedelta(days=100)
YESTERDAY = TODAY - dt.timedelta(days=1)
PAST = TODAY - dt.timedelta(days=10)
FAR_PAST = TODAY - dt.timedelta(days=100)
def _assert_path_and_context(
self, xblock, expected_path, expected_context,
workflow_status, deadline_information, has_peers_to_grade
):
"""
Complete all of the logic behind rendering the message and verify
1) The correct template and context were used
2) The rendering occured without an error
Args:
xblock (OpenAssessmentBlock): The XBlock we are testing
expected_path (str): The expected template path
expected_context (dict): The expected template context
workflow_status (str or None): The cannonical workflow status
deadline_information (dict): has the following properties
- deadline_information.get("submission") has the same properties as is_closed("submission")
- deadline_information.get("peer-assessment") has the same properties as is_closed("peer-assessment")
- deadline_information.get("self-assessment") has the same properties as is_closed("self-assessment")
- (WILL BE DEFAULT) deadline_information.get("over-all") has the same properties as is_closed()
has_peers_to_grade (bool): A boolean which indicates whether the queue of peer responses is empty
"""
# Simulate the response from the workflow API
workflow_info = {
'status': workflow_status
}
xblock.get_workflow_info = mock.Mock(return_value=workflow_info)
# Mock out the actual rendering of the assessment (we will check what it is called with)
xblock.render_assessment = mock.Mock()
# Simulate the field of no_peers based on our test input
xblock.no_peers = not has_peers_to_grade
# Mock out the is_closed method from the OpenAssessmentClass
with mock.patch.object(OpenAssessmentBlock, 'is_closed') as mock_is_closed:
def closed_side_effect(step="over-all"):
# The method which will patch xblock.is_closed. Returns values in the form of is_closed, and takes
# its information from the paramater deadline_information of _assert_path_and_context.
# Note that if no parameter is provided, we assume the user is asking for is_closed()
return deadline_information.get(step, "not-found")
# Sets the side effect of is_closed to be our custom method, completing the patch
mock_is_closed.side_effect = closed_side_effect
# self.request(xblock, 'render_message', )
#from nose.tools import set_trace; set_trace()
xblock.render_message(None, '')
# Asserts that the message_mixin correctly derived the path and context to be rendered
xblock.render_assessment.assert_called_with(expected_path, expected_context)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_submission(self, xblock):
status = None
deadline_information = {
'submission': (False, None, self.FAR_PAST, self.FUTURE),
'peer-assessment': (False, None, self.FAR_PAST, self.FAR_FUTURE),
'self-assessment': (False, None, self.FAR_PAST, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_open.html'
expected_context = {
"approaching": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_no_peer.xml', user_id = "Linda")
def test_submission_no_peer(self, xblock):
status = None
deadline_information = {
'submission': (False, None, self.FAR_PAST, self.FUTURE),
'self-assessment': (True, 'start', self.FUTURE, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_open.html'
expected_context = {
"approaching": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_submission_approaching(self, xblock):
status = None
deadline_information = {
'submission': (False, None, self.FAR_PAST, self.TOMORROW),
'peer-assessment': (False, None, self.FAR_PAST, self.FAR_FUTURE),
'self-assessment': (True, 'start', self.FUTURE, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = True
expected_path = 'openassessmentblock/message/oa_message_open.html'
expected_context = {
"approaching": True
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_no_self.xml', user_id = "Linda")
def test_submission_no_self_approaching(self, xblock):
status = None
deadline_information = {
'submission': (False, None, self.FAR_PAST, self.TOMORROW),
'peer-assessment': (False, None, self.FAR_PAST, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_open.html'
expected_context = {
"approaching": True
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_submission_not_yet_open(self, xblock):
status = None
deadline_information = {
'submission': (True, 'start', self.TOMORROW, self.FAR_FUTURE),
'peer-assessment': (True, 'start', self.TOMORROW, self.FAR_FUTURE),
'self-assessment': (True, 'start', self.TOMORROW, self.FAR_FUTURE),
'over-all': (True, 'start', self.TOMORROW, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_closed.html'
expected_context = {
"not_yet_open": True
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_submission_incomplete(self, xblock):
status = None
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.TODAY),
'peer-assessment': (True, 'start', self.TOMORROW, self.FAR_FUTURE),
'self-assessment': (True, 'start', self.TOMORROW, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_closed.html'
expected_context = {
"not_yet_open": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_student_training.xml', user_id = "Linda")
def test_training(self, xblock):
status = 'training'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'student-training': (False, None, self.YESTERDAY, self.FUTURE),
'peer-assessment': (False, None, self.YESTERDAY, self.FUTURE),
'self-assessment': (True, 'start', self.TOMORROW, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = True
expected_path = 'openassessmentblock/message/oa_message_training.html'
expected_context = {
"approaching": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_student_training.xml', user_id = "Linda")
def test_training_approaching(self, xblock):
status = 'training'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'student-training': (False, None, self.YESTERDAY, self.TOMORROW),
'peer-assessment': (False, None, self.YESTERDAY, self.TOMORROW),
'self-assessment': (True, 'start', self.TOMORROW, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_training.html'
expected_context = {
"approaching": True
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_student_training.xml', user_id = "Linda")
def test_training_not_released(self, xblock):
status = 'training'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.TOMORROW),
'student-training': (True, 'start', self.TOMORROW, self.FUTURE),
'peer-assessment': (True, 'start', self.TOMORROW, self.FUTURE),
'self-assessment': (True, 'start', self.TOMORROW, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_closed.html'
expected_context = {
"not_yet_open": True
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_student_training.xml', user_id = "Linda")
def test_training_closed(self, xblock):
status = 'training'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.PAST),
'student-training': (True, 'due', self.FAR_PAST, self.PAST),
'peer-assessment': (True, 'due', self.PAST, self.YESTERDAY),
'self-assessment': (False, None, self.YESTERDAY, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_closed.html'
expected_context = {
"not_yet_open": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_peer(self, xblock):
status = 'peer'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (False, None, self.FAR_PAST, self.FUTURE),
'self-assessment': (False, None, self.FAR_PAST, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = True
expected_path = 'openassessmentblock/message/oa_message_peer.html'
expected_context = {
"has_self": True,
"waiting": False,
"peer_approaching": False,
"peer_closed": False,
"peer_not_released": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_no_self.xml', user_id = "Linda")
def test_peer_no_self(self, xblock):
status = 'peer'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (False, None, self.FAR_PAST, self.FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = True
expected_path = 'openassessmentblock/message/oa_message_peer.html'
expected_context = {
"has_self": False,
"waiting": False,
"peer_approaching": False,
"peer_closed": False,
"peer_not_released": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_no_self.xml', user_id = "Linda")
def test_peer_no_self_approaching(self, xblock):
status = 'peer'
deadline_information = {
'submission': (False, None, self.FAR_PAST, self.TOMORROW),
'peer-assessment': (False, None, self.FAR_PAST, self.TOMORROW),
'over-all': (False, None, self.FAR_PAST, self.TOMORROW)
}
has_peers_to_grade = True
expected_path = 'openassessmentblock/message/oa_message_peer.html'
expected_context = {
"has_self": False,
"waiting": False,
"peer_approaching": True,
"peer_closed": False,
"peer_not_released": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_peer_not_released(self, xblock):
status = 'peer'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (True, 'start', self.TOMORROW, self.FUTURE),
'self-assessment': (True, 'start', self.TOMORROW, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = True
expected_path = 'openassessmentblock/message/oa_message_closed.html'
expected_context = {
"not_yet_open": True
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_peer_incomplete(self, xblock):
status = 'peer'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (True, 'due', self.PAST, self.TODAY),
'self-assessment': (False, None, self.TODAY, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = True
expected_path = 'openassessmentblock/message/oa_message_closed.html'
expected_context = {
"not_yet_open": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_peer_no_peers_to_assess(self, xblock):
status = 'peer'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (False, None, self.FAR_PAST, self.FUTURE),
'self-assessment': (False, None, self.FAR_PAST, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_peer.html'
expected_context = {
"has_self": True,
"waiting": True,
"peer_approaching": False,
"peer_closed": False,
"peer_not_released": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_peer_no_peers_to_assess_approaching(self, xblock):
status = 'peer'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (False, None, self.FAR_PAST, self.TOMORROW),
'self-assessment': (False, None, self.FAR_PAST, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_peer.html'
expected_context = {
"has_self": True,
"waiting": True,
"peer_approaching": True,
"peer_closed": False,
"peer_not_released": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_peer_not_open_approaching(self, xblock):
status = 'peer'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (True, 'start', self.TOMORROW, self.FUTURE),
'self-assessment': (False, None, self.FUTURE, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_closed.html'
expected_context = {
"not_yet_open": True
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_self(self, xblock):
status = 'self'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (False, None, self.FAR_PAST, self.FUTURE),
'self-assessment': (False, None, self.FAR_PAST, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_self.html'
expected_context = {
"has_peer": True,
"self_approaching": False,
"self_closed": False,
"self_not_released": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_no_peer.xml', user_id = "Linda")
def test_self_no_peer(self, xblock):
status = 'self'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'self-assessment': (False, None, self.FAR_PAST, self.FAR_FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FAR_FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_self.html'
expected_context = {
"has_peer": False,
"self_approaching": False,
"self_closed": False,
"self_not_released": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_no_peer.xml', user_id = "Linda")
def test_self_no_peer_approaching(self, xblock):
status = 'self'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'self-assessment': (False, None, self.FAR_PAST, self.TOMORROW),
'over-all': (False, None, self.FAR_PAST, self.TOMORROW)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_self.html'
expected_context = {
"has_peer": False,
"self_approaching": True,
"self_closed": False,
"self_not_released": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_self_closed(self, xblock):
status = 'self'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (True, 'due', self.YESTERDAY, self.TODAY),
'self-assessment': (True, 'start', self.TOMORROW, self.FUTURE),
'over-all': (False, None, self.FAR_PAST, self.FUTURE)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_closed.html'
expected_context = {
"not_yet_open": True
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario_no_peer.xml', user_id = "Linda")
def test_self_no_peer_incomplete(self, xblock):
status = 'self'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'self-assessment': (True, 'due', self.PAST, self.YESTERDAY),
'over-all': (True, 'due', self.FAR_PAST, self.YESTERDAY)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_closed.html'
expected_context = {
"not_yet_open": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_waiting_due(self, xblock):
status = 'waiting'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (True, 'due', self.YESTERDAY, self.TODAY),
'self-assessment': (True, 'due', self.YESTERDAY, self.TODAY),
'over-all': (True, 'due', self.FAR_PAST, self.TODAY)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_complete.html'
expected_context = {
"waiting": True
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_waiting_not_due(self, xblock):
status = 'waiting'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (True, 'due', self.YESTERDAY, self.TODAY),
'self-assessment': (False, None, self.YESTERDAY, self.TOMORROW),
'over-all': (False, None, self.FAR_PAST, self.TOMORROW)
}
has_peers_to_grade = True
expected_path = 'openassessmentblock/message/oa_message_complete.html'
expected_context = {
"waiting": True
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_done_due(self, xblock):
status = 'done'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (True, 'due', self.YESTERDAY, self.TODAY),
'self-assessment': (True, 'due', self.YESTERDAY, self.TODAY),
'over-all': (True, 'due', self.FAR_PAST, self.TODAY)
}
has_peers_to_grade = True
expected_path = 'openassessmentblock/message/oa_message_complete.html'
expected_context = {
"waiting": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
@scenario('data/message_scenario.xml', user_id = "Linda")
def test_done_not_due(self, xblock):
status = 'done'
deadline_information = {
'submission': (True, 'due', self.FAR_PAST, self.YESTERDAY),
'peer-assessment': (True, 'due', self.YESTERDAY, self.TODAY),
'self-assessment': (False, None, self.YESTERDAY, self.TOMORROW),
'over-all': (False, None, self.FAR_PAST, self.TOMORROW)
}
has_peers_to_grade = False
expected_path = 'openassessmentblock/message/oa_message_complete.html'
expected_context = {
"waiting": False
}
self._assert_path_and_context(
xblock, expected_path, expected_context,
status, deadline_information, has_peers_to_grade
)
\ No newline at end of file
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