Commit 7a0f19be by Jonathan Piacenti

Add support for 'assessment feedback' message.

parent 18ebc3bf
...@@ -335,6 +335,21 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC ...@@ -335,6 +335,21 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC
return {'result': 'ok'} return {'result': 'ok'}
def get_message(self, completed):
if self.max_attempts_reached:
return self.get_message_html('max_attempts_reached')
elif completed:
return self.get_message_html('completed')
else:
return self.get_message_html('incomplete')
@property
def assessment_message(self):
if not self.max_attempts_reached:
return self.get_message_html('on-assessment-review')
else:
return None
@XBlock.json_handler @XBlock.json_handler
def submit(self, submissions, suffix=''): def submit(self, submissions, suffix=''):
log.info(u'Received submissions: {}'.format(submissions)) log.info(u'Received submissions: {}'.format(submissions))
...@@ -354,12 +369,7 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC ...@@ -354,12 +369,7 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC
child.save() child.save()
completed = completed and (child_result['status'] == 'correct') completed = completed and (child_result['status'] == 'correct')
if self.max_attempts_reached: message = self.get_message(completed)
message = self.get_message_html('max_attempts_reached')
elif completed:
message = self.get_message_html('completed')
else:
message = self.get_message_html('incomplete')
# Once it has been completed once, keep completion even if user changes values # Once it has been completed once, keep completion even if user changes values
if self.completed: if self.completed:
...@@ -416,6 +426,7 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC ...@@ -416,6 +426,7 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC
children = [self.runtime.get_block(child_id) for child_id in self.children] children = [self.runtime.get_block(child_id) for child_id in self.children]
children = [child for child in children if not isinstance(child, MentoringMessageBlock)] children = [child for child in children if not isinstance(child, MentoringMessageBlock)]
steps = [child for child in children if isinstance(child, StepMixin)] # Faster than the self.steps property steps = [child for child in children if isinstance(child, StepMixin)] # Faster than the self.steps property
assessment_message = None
for child in children: for child in children:
if child.name and child.name in submissions: if child.name and child.name in submissions:
...@@ -451,6 +462,7 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC ...@@ -451,6 +462,7 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC
'score_type': 'proficiency', 'score_type': 'proficiency',
}) })
event_data['final_grade'] = score.raw event_data['final_grade'] = score.raw
assessment_message = self.assessment_message
self.num_attempts += 1 self.num_attempts += 1
self.completed = True self.completed = True
...@@ -471,6 +483,7 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC ...@@ -471,6 +483,7 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC
'correct_answer': score.correct, 'correct_answer': score.correct,
'incorrect_answer': score.incorrect, 'incorrect_answer': score.incorrect,
'partially_correct_answer': score.partially_correct, 'partially_correct_answer': score.partially_correct,
'assessment_message': assessment_message,
} }
@XBlock.json_handler @XBlock.json_handler
......
...@@ -56,6 +56,7 @@ class MentoringMessageBlock(XBlock, StudioEditableXBlockMixin): ...@@ -56,6 +56,7 @@ class MentoringMessageBlock(XBlock, StudioEditableXBlockMixin):
{"display_name": "Completed", "value": "completed"}, {"display_name": "Completed", "value": "completed"},
{"display_name": "Incompleted", "value": "incomplete"}, {"display_name": "Incompleted", "value": "incomplete"},
{"display_name": "Reached max. # of attemps", "value": "max_attempts_reached"}, {"display_name": "Reached max. # of attemps", "value": "max_attempts_reached"},
{"display_name": "Review with attempts left", "value": "on_assessment_review"}
), ),
) )
editable_fields = ("content", ) editable_fields = ("content", )
...@@ -84,6 +85,8 @@ class MentoringMessageBlock(XBlock, StudioEditableXBlockMixin): ...@@ -84,6 +85,8 @@ class MentoringMessageBlock(XBlock, StudioEditableXBlockMixin):
return self._(u"Message shown when complete") return self._(u"Message shown when complete")
if self.type == 'incomplete': if self.type == 'incomplete':
return self._(u"Message shown when incomplete") return self._(u"Message shown when incomplete")
if self.type == 'on-assessment-review':
return self._(u"Message shown during review when attempts remain")
return u"INVALID MESSAGE" return u"INVALID MESSAGE"
@classmethod @classmethod
......
...@@ -2,14 +2,16 @@ ...@@ -2,14 +2,16 @@
margin: 1em 0em; margin: 1em 0em;
} }
.mentoring .messages { .mentoring .messages,
.mentoring .assessment-messages {
display: none; display: none;
margin-top: 10px; margin-top: 10px;
border-top: 2px solid #eaeaea; border-top: 2px solid #eaeaea;
padding: 12px 0px 20px; padding: 12px 0px 20px;
} }
.mentoring .messages .title1 { .mentoring .messages .title1,
.mentoring .assessment-messages .title1 {
color: #333333; color: #333333;
text-transform: uppercase; text-transform: uppercase;
font-weight: bold; font-weight: bold;
......
function MentoringAssessmentView(runtime, element, mentoring) { function MentoringAssessmentView(runtime, element, mentoring) {
var gradeTemplate = _.template($('#xblock-grade-template').html()); var gradeTemplate = _.template($('#xblock-grade-template').html());
var submitDOM, nextDOM, reviewDOM, tryAgainDOM; var submitDOM, nextDOM, reviewDOM, tryAgainDOM, messagesDOM;
var submitXHR; var submitXHR;
var checkmark; var checkmark;
var active_child; var active_child;
...@@ -21,6 +21,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { ...@@ -21,6 +21,7 @@ function MentoringAssessmentView(runtime, element, mentoring) {
$('.grade').html(''); $('.grade').html('');
$('.attempts').html(''); $('.attempts').html('');
messagesDOM.empty().hide();
} }
function renderGrade() { function renderGrade() {
...@@ -42,6 +43,10 @@ function MentoringAssessmentView(runtime, element, mentoring) { ...@@ -42,6 +43,10 @@ function MentoringAssessmentView(runtime, element, mentoring) {
} }
mentoring.renderAttempts(); mentoring.renderAttempts();
if (data.assessment_message && data.num_attempts < data.max_attempts) {
mentoring.setContent(messagesDOM, data.assessment_message);
messagesDOM.show();
}
} }
function handleTryAgain(result) { function handleTryAgain(result) {
...@@ -74,6 +79,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { ...@@ -74,6 +79,7 @@ function MentoringAssessmentView(runtime, element, mentoring) {
reviewDOM = $(element).find('.submit .input-review'); reviewDOM = $(element).find('.submit .input-review');
tryAgainDOM = $(element).find('.submit .input-try-again'); tryAgainDOM = $(element).find('.submit .input-try-again');
checkmark = $('.assessment-checkmark', element); checkmark = $('.assessment-checkmark', element);
messagesDOM = $('.assessment-messages', element);
submitDOM.show(); submitDOM.show();
submitDOM.bind('click', submit); submitDOM.bind('click', submit);
...@@ -149,6 +155,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { ...@@ -149,6 +155,7 @@ function MentoringAssessmentView(runtime, element, mentoring) {
$('.grade', element).data('partially_correct_answer', result.partially_correct_answer); $('.grade', element).data('partially_correct_answer', result.partially_correct_answer);
$('.grade', element).data('max_attempts', result.max_attempts); $('.grade', element).data('max_attempts', result.max_attempts);
$('.grade', element).data('num_attempts', result.num_attempts); $('.grade', element).data('num_attempts', result.num_attempts);
$('.grade', element).data('assessment_message', result.assessment_message);
$('.attempts', element).data('max_attempts', result.max_attempts); $('.attempts', element).data('max_attempts', result.max_attempts);
$('.attempts', element).data('num_attempts', result.num_attempts); $('.attempts', element).data('num_attempts', result.num_attempts);
......
...@@ -25,9 +25,12 @@ ...@@ -25,9 +25,12 @@
data-incorrect_answer="{{ self.score.3 }}" data-incorrect_answer="{{ self.score.3 }}"
data-partially_correct_answer="{{ self.score.4 }}" data-partially_correct_answer="{{ self.score.4 }}"
data-max_attempts="{{ self.max_attempts }}" data-max_attempts="{{ self.max_attempts }}"
data-num_attempts="{{ self.num_attempts }}"> data-num_attempts="{{ self.num_attempts }}"
data-assessment_message="{{ self.assessment_message }}">
</div> </div>
<div class="assessment-messages"></div>
<div class="submit"> <div class="submit">
{% if self.mode == 'assessment' %} {% if self.mode == 'assessment' %}
<span class="assessment-checkmark fa icon-2x"></span> <span class="assessment-checkmark fa icon-2x"></span>
......
<vertical_demo>
<problem-builder url_name="mcq_with_comments" display_name="MCQ With Resizable popups" weight="1" enforce_dependency="false">
<pb-mcq name="mrq_1_1_7" question="What do you like in this MCQ?" correct_choices="gracefulness,elegance,beauty">
<pb-choice value="elegance"><strong>Its elegance</strong></pb-choice>
<pb-choice value="beauty"><em>Its beauty</em></pb-choice>
<pb-choice value="gracefulness"><strong>Its gracefulness</strong></pb-choice>
<pb-choice value="bugs"><span style="font-color:red">Its bugs</span></pb-choice>
<pb-tip values="gracefulness" width ="200" height = "200">This MCQ is indeed very graceful</pb-tip>
<pb-tip values="elegance" width ="600" height = "800">This is something everyone has to like about this MCQ</pb-tip>
<pb-tip values="beauty" width ="400" height = "600">This is something everyone has to like about beauty</pb-tip>
<pb-tip values="bugs" width = "100" height = "200">Nah, there isn\'t any!</pb-tip>
</pb-mcq>
<pb-message type="completed">
<p>Congratulations!</p>
</pb-message>
<pb-message type="incomplete">
<p>Still some work to do...</p>
</pb-message>
</problem-builder>
</vertical_demo>
...@@ -36,4 +36,7 @@ ...@@ -36,4 +36,7 @@
<pb-tip values="elegance,beauty">This is something everyone has to like about this MRQ</pb-tip> <pb-tip values="elegance,beauty">This is something everyone has to like about this MRQ</pb-tip>
<pb-tip values="bugs">Nah, there isn't any!</pb-tip> <pb-tip values="bugs">Nah, there isn't any!</pb-tip>
</pb-mrq> </pb-mrq>
<pb-message type="on-assessment-review">
<html>Assessment additional feedback message text</html>
</pb-message>
</problem-builder> </problem-builder>
...@@ -256,6 +256,17 @@ class MentoringAssessmentTest(MentoringAssessmentBaseTest): ...@@ -256,6 +256,17 @@ class MentoringAssessmentTest(MentoringAssessmentBaseTest):
self.assert_hidden(controls.next_question) self.assert_hidden(controls.next_question)
self.assert_hidden(controls.review) self.assert_hidden(controls.review)
def assert_messages_text(self, mentoring, text):
messages = mentoring.find_element_by_css_selector('.assessment-messages')
self.assertEqual(messages.text, text)
self.assertTrue(messages.is_displayed())
def assert_messages_empty(self, mentoring):
messages = mentoring.find_element_by_css_selector('.assessment-messages')
self.assertEqual(messages.text, '')
self.assertFalse(messages.find_elements_by_xpath('./*'))
self.assertFalse(messages.is_displayed())
def test_assessment(self): def test_assessment(self):
mentoring, controls = self.go_to_assessment("Assessment 1") mentoring, controls = self.go_to_assessment("Assessment 1")
...@@ -276,6 +287,7 @@ class MentoringAssessmentTest(MentoringAssessmentBaseTest): ...@@ -276,6 +287,7 @@ class MentoringAssessmentTest(MentoringAssessmentBaseTest):
} }
self.peek_at_review(mentoring, controls, expected_results) self.peek_at_review(mentoring, controls, expected_results)
self.assert_messages_text(mentoring, "Assessment additional feedback message text")
self.assert_clickable(controls.try_again) self.assert_clickable(controls.try_again)
controls.try_again.click() controls.try_again.click()
...@@ -294,6 +306,7 @@ class MentoringAssessmentTest(MentoringAssessmentBaseTest): ...@@ -294,6 +306,7 @@ class MentoringAssessmentTest(MentoringAssessmentBaseTest):
} }
self.peek_at_review(mentoring, controls, expected_results) self.peek_at_review(mentoring, controls, expected_results)
self.assert_disabled(controls.try_again) self.assert_disabled(controls.try_again)
self.assert_messages_empty(mentoring)
def test_single_question_assessment(self): def test_single_question_assessment(self):
""" """
...@@ -308,6 +321,7 @@ class MentoringAssessmentTest(MentoringAssessmentBaseTest): ...@@ -308,6 +321,7 @@ class MentoringAssessmentTest(MentoringAssessmentBaseTest):
} }
self.peek_at_review(mentoring, controls, expected_results) self.peek_at_review(mentoring, controls, expected_results)
self.assert_messages_empty(mentoring)
controls.try_again.click() controls.try_again.click()
# this is a wait and assertion all together - it waits until expected text is in mentoring block # this is a wait and assertion all together - it waits until expected text is in mentoring block
......
...@@ -42,4 +42,8 @@ ...@@ -42,4 +42,8 @@
<pb-tip values='["elegance","beauty"]'>This is something everyone has to like about this MRQ</pb-tip> <pb-tip values='["elegance","beauty"]'>This is something everyone has to like about this MRQ</pb-tip>
<pb-tip values='["bugs"]'>Nah, there isn't any!</pb-tip> <pb-tip values='["bugs"]'>Nah, there isn't any!</pb-tip>
</pb-mrq> </pb-mrq>
<pb-message type="on-assessment-review">
<html>Assessment additional feedback message text</html>
</pb-message>
</problem-builder> </problem-builder>
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