Commit e87453b7 by Braden MacDonald

Merge pull request #52 from open-craft/hgse-fixes-iii

Fix two bugs (OC-839)
parents 21fc19e0 0bf1ae61
...@@ -85,6 +85,23 @@ class AnswerMixin(object): ...@@ -85,6 +85,23 @@ class AnswerMixin(object):
) )
return answer_data return answer_data
@property
def student_input(self):
if self.name:
return self.get_model_object().student_input
return ''
@XBlock.json_handler
def answer_value(self, data, suffix=''):
""" Current value of the answer, for refresh by client """
return {'value': self.student_input}
@XBlock.json_handler
def refresh_html(self, data, suffix=''):
""" Complete HTML view of the XBlock, for refresh by client """
frag = self.mentoring_view({})
return {'html': frag.content}
def validate_field_data(self, validation, data): def validate_field_data(self, validation, data):
""" """
Validate this block's field data. Validate this block's field data.
...@@ -277,12 +294,6 @@ class AnswerRecapBlock(AnswerMixin, StudioEditableXBlockMixin, XBlock): ...@@ -277,12 +294,6 @@ class AnswerRecapBlock(AnswerMixin, StudioEditableXBlockMixin, XBlock):
css_path = 'public/css/answer.css' css_path = 'public/css/answer.css'
@property
def student_input(self):
if self.name:
return self.get_model_object().student_input
return ''
def mentoring_view(self, context=None): def mentoring_view(self, context=None):
""" Render this XBlock within a mentoring block. """ """ Render this XBlock within a mentoring block. """
context = context.copy() if context else {} context = context.copy() if context else {}
...@@ -308,6 +319,8 @@ class AnswerRecapBlock(AnswerMixin, StudioEditableXBlockMixin, XBlock): ...@@ -308,6 +319,8 @@ class AnswerRecapBlock(AnswerMixin, StudioEditableXBlockMixin, XBlock):
fragment = Fragment(html) fragment = Fragment(html)
fragment.add_css_url(self.runtime.local_resource_url(self, self.css_path)) fragment.add_css_url(self.runtime.local_resource_url(self, self.css_path))
fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/answer_recap.js'))
fragment.initialize_js('AnswerRecapBlock')
return fragment return fragment
def student_view(self, context=None): def student_view(self, context=None):
......
...@@ -759,10 +759,16 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC ...@@ -759,10 +759,16 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC
""" """
By default, each Sequential block in a course ("Subsection" in Studio parlance) will By default, each Sequential block in a course ("Subsection" in Studio parlance) will
display the display_name of each descendant in a tooltip above the content. We don't display the display_name of each descendant in a tooltip above the content. We don't
want that - we only want to display the mentoring block as a whole as one item. want that - we only want to display one title for this mentoring block as a whole.
Otherwise things like "Choice (yes) (Correct)" will appear in the tooltip. Otherwise things like "Choice (yes) (Correct)" will appear in the tooltip.
If this block has no title set, don't display any title. Then, if this is the only block
in the unit, the unit's title will be used. (Why isn't it always just used?)
""" """
has_explicitly_set_title = self.fields['display_name'].is_set_on(self)
if has_explicitly_set_title:
return [self.display_name] return [self.display_name]
return []
@staticmethod @staticmethod
def workbench_scenarios(): def workbench_scenarios():
......
...@@ -11,6 +11,11 @@ function AnswerBlock(runtime, element) { ...@@ -11,6 +11,11 @@ function AnswerBlock(runtime, element) {
if (completed === 'True' && this.mode === 'standard') { if (completed === 'True' && this.mode === 'standard') {
checkmark.addClass('checkmark-correct icon-ok fa-check'); checkmark.addClass('checkmark-correct icon-ok fa-check');
} }
// In the LMS, the HTML of multiple units can be loaded at once,
// and the user can flip among them. If that happens, the answer in
// our HTML may be out of date.
this.refreshAnswer();
}, },
submit: function() { submit: function() {
...@@ -69,6 +74,25 @@ function AnswerBlock(runtime, element) { ...@@ -69,6 +74,25 @@ function AnswerBlock(runtime, element) {
} }
} }
return true; return true;
},
refreshAnswer: function() {
$.ajax({
type: 'POST',
url: runtime.handlerUrl(element, 'answer_value'),
data: '{}',
dataType: 'json',
success: function(data) {
// Update the answer to the latest, unless the user has made an edit
var newAnswer = data.value;
var $textarea = $(':input', element);
var currentAnswer = $textarea.val();
var origAnswer = $('.orig-student-answer', element).text();
if (currentAnswer == origAnswer && currentAnswer != newAnswer) {
$textarea.val(newAnswer);
}
},
});
} }
}; };
} }
function AnswerRecapBlock(runtime, element) {
return {
init: function(options) {
// In the LMS, the HTML of multiple units can be loaded at once,
// and the user can flip among them. If that happens, the answer in
// our HTML may be out of date.
this.refreshAnswer();
},
refreshAnswer: function() {
$.ajax({
type: 'POST',
url: runtime.handlerUrl(element, 'refresh_html'),
data: '{}',
dataType: 'json',
success: function(data) {
$(element).html(data.html);
}
});
}
};
}
...@@ -5,5 +5,6 @@ ...@@ -5,5 +5,6 @@
class="answer editable" cols="50" rows="10" name="input" class="answer editable" cols="50" rows="10" name="input"
data-min_characters="{{ self.min_characters }}" data-min_characters="{{ self.min_characters }}"
>{{ self.student_input }}</textarea> >{{ self.student_input }}</textarea>
<div style="display: none;" class="orig-student-answer">{{ self.student_input }}</div> <!-- To detect edits -->
<span class="answer-checkmark fa icon-2x"></span> <span class="answer-checkmark fa icon-2x"></span>
</div> </div>
{% load i18n %} {% load i18n %}
<div class="xblock-answer" data-completed="{{ student_input|yesno:"true,false" }}"> <div class="xblock-answer">
{% if not hide_header %}<h3 class="question-title">{{ title }}</h3>{% endif %} {% if not hide_header %}<h3 class="question-title">{{ title }}</h3>{% endif %}
{% if description %}<p>{{ description|safe }}</p>{% endif %} {% if description %}<p>{{ description|safe }}</p>{% endif %}
<blockquote class="answer read_only"> <blockquote class="answer read_only">
......
...@@ -6,6 +6,7 @@ from problem_builder import MentoringBlock ...@@ -6,6 +6,7 @@ from problem_builder import MentoringBlock
from problem_builder.mentoring import _default_theme_config from problem_builder.mentoring import _default_theme_config
@ddt.ddt
class TestMentoringBlock(unittest.TestCase): class TestMentoringBlock(unittest.TestCase):
def test_sends_progress_event_when_rendered_student_view_with_display_submit_false(self): def test_sends_progress_event_when_rendered_student_view_with_display_submit_false(self):
block = MentoringBlock(MagicMock(), DictFieldData({ block = MentoringBlock(MagicMock(), DictFieldData({
...@@ -31,6 +32,21 @@ class TestMentoringBlock(unittest.TestCase): ...@@ -31,6 +32,21 @@ class TestMentoringBlock(unittest.TestCase):
self.assertFalse(patched_runtime.publish.called) self.assertFalse(patched_runtime.publish.called)
@ddt.data(True, False)
def test_get_content_titles(self, has_title_set):
"""
Test that we don't send a title to the LMS for the sequential's tooltips when no title
is set
"""
if has_title_set:
data = {'display_name': 'Custom Title'}
expected = ['Custom Title']
else:
data = {}
expected = []
block = MentoringBlock(MagicMock(), DictFieldData(data), Mock())
self.assertEqual(block.get_content_titles(), expected)
@ddt.ddt @ddt.ddt
class TestMentoringBlockTheming(unittest.TestCase): class TestMentoringBlockTheming(unittest.TestCase):
......
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