Commit 7904214c by Xavier Antoviaque

Support multiple tips for a single quizz, each with its own conditions

parent 9f2e5bc1
from .answer import AnswerBlock from .answer import AnswerBlock
from .quizz import QuizzBlock from .quizz import QuizzBlock, QuizzTipBlock
from .mentoring import MentoringBlock from .mentoring import MentoringBlock
...@@ -3,11 +3,10 @@ ...@@ -3,11 +3,10 @@
# Imports ########################################################### # Imports ###########################################################
import copy
import logging import logging
from xblock.core import XBlock from xblock.core import XBlock
from xblock.fields import List, Scope, String from xblock.fields import Scope, String
from xblock.fragment import Fragment from xblock.fragment import Fragment
from .utils import load_resource, render_template from .utils import load_resource, render_template
...@@ -47,9 +46,7 @@ class QuizzBlock(XBlock): ...@@ -47,9 +46,7 @@ class QuizzBlock(XBlock):
student_choice = String(help="Last input submitted by the student", default="", scope=Scope.user_state) student_choice = String(help="Last input submitted by the student", default="", scope=Scope.user_state)
low = String(help="Label for low ratings", scope=Scope.content, default="Less") low = String(help="Label for low ratings", scope=Scope.content, default="Less")
high = String(help="Label for high ratings", scope=Scope.content, default="More") high = String(help="Label for high ratings", scope=Scope.content, default="More")
tip = String(help="Mentoring tip to provide if needed", scope=Scope.content, default="") has_children = True
display = List(help="List of choices to display the tip for", scope=Scope.content, default=None)
reject = List(help="List of choices to reject", scope=Scope.content, default=None)
@classmethod @classmethod
def parse_xml(cls, node, runtime, keys): def parse_xml(cls, node, runtime, keys):
...@@ -58,10 +55,6 @@ class QuizzBlock(XBlock): ...@@ -58,10 +55,6 @@ class QuizzBlock(XBlock):
for child in node: for child in node:
if child.tag == "question": if child.tag == "question":
block.question = child.text block.question = child.text
elif child.tag == "tip":
block.tip = child.text
block.reject = commas_to_list(child.get('reject'))
block.display = commas_to_list(child.get('display'))
else: else:
block.runtime.add_node_as_child(block, child) block.runtime.add_node_as_child(block, child)
...@@ -93,47 +86,85 @@ class QuizzBlock(XBlock): ...@@ -93,47 +86,85 @@ class QuizzBlock(XBlock):
def submit(self, submission): def submit(self, submission):
log.debug(u'Received quizz submission: "%s"', submission) log.debug(u'Received quizz submission: "%s"', submission)
completed = self.is_completed(submission) completed = True
show_tip = self.is_tip_shown(submission) formatted_tips_list = []
self.student_choice = submission for tip in self.get_tips():
completed = completed and tip.is_completed(submission)
if tip.is_tip_displayed(submission):
formatted_tips_list.append(tip.render(submission))
if show_tip: if formatted_tips_list:
formatted_tip = render_template('templates/html/tip.html', { formatted_tips = render_template('templates/html/tip_group.html', {
'self': self, 'self': self,
'tips': formatted_tips_list,
'submission': submission,
}) })
else: else:
formatted_tip = '' formatted_tips = u''
self.student_choice = submission
result = { result = {
'submission': submission, 'submission': submission,
'completed': completed, 'completed': completed,
'tip': formatted_tip, 'tips': formatted_tips,
} }
log.debug(u'Quizz submission result: %s', result) log.debug(u'Quizz submission result: %s', result)
return result return result
def get_tips(self):
"""
Returns the tips contained in this block
"""
tips = []
for child_id in self.children: # pylint: disable=E1101
child = self.runtime.get_block(child_id)
if child.xml_element_name() == 'tip':
tips.append(child)
return tips
class QuizzTipBlock(XBlock):
"""
Each quizz
"""
content = String(help="Text of the tip to provide if needed", scope=Scope.content, default="")
display = String(help="List of choices to display the tip for", scope=Scope.content, default=None)
reject = String(help="List of choices to reject", scope=Scope.content, default=None)
def render(self, submission):
"""
Returns a string containing the formatted tip
"""
return render_template('templates/html/tip.html', {
'self': self,
})
def is_completed(self, submission): def is_completed(self, submission):
return submission and submission not in self.reject_with_defaults return submission and submission not in self.reject_with_defaults
def is_tip_shown(self, submission): def is_tip_displayed(self, submission):
return not submission or submission in self.display_with_defaults return not submission or submission in self.display_with_defaults
@property @property
def reject_with_defaults(self): def reject_with_defaults(self):
if self.reject is None: reject = commas_to_list(self.reject)
if self.type == 'yes-no-unsure': log.debug(reject)
if reject is None:
quizz = self.runtime.get_block(self.parent)
if quizz.type == 'yes-no-unsure':
return ['no', 'unsure'] return ['no', 'unsure']
elif self.type == 'rating': elif quizz.type == 'rating-unsure':
return ['1', '2', '3'] return ['1', '2', '3', 'unsure']
else: else:
return self.reject return reject
@property @property
def display_with_defaults(self): def display_with_defaults(self):
display = copy.copy(self.display) display = commas_to_list(self.display)
if display is None: if display is None:
display = self.reject_with_defaults display = self.reject_with_defaults
else: else:
display += [choice for choice in self.reject_with_defaults display += [choice for choice in self.reject_with_defaults
if choice not in display] if choice not in display]
return display return display
...@@ -4,6 +4,7 @@ BLOCKS = [ ...@@ -4,6 +4,7 @@ BLOCKS = [
'mentoring = mentoring:MentoringBlock', 'mentoring = mentoring:MentoringBlock',
'answer = mentoring:AnswerBlock', 'answer = mentoring:AnswerBlock',
'quizz = mentoring:QuizzBlock', 'quizz = mentoring:QuizzBlock',
'tip = mentoring:QuizzTipBlock',
] ]
setup( setup(
......
...@@ -11,7 +11,7 @@ function QuizzBlock(runtime, element) { ...@@ -11,7 +11,7 @@ function QuizzBlock(runtime, element) {
}, },
handleSubmit: function(result) { handleSubmit: function(result) {
var tipsDom = $(element).parent().find('.messages'), var tipsDom = $(element).parent().find('.messages'),
tipHtml = (result || {}).tip || ''; tipHtml = (result || {}).tips || '';
if(tipHtml) { if(tipHtml) {
tipsDom.append(tipHtml); tipsDom.append(tipHtml);
......
<fieldset class="rating"> <fieldset class="rating-unsure">
<legend>{{ self.question }}</legend> <legend>{{ self.question }}</legend>
<div class="choices"> <div class="choices">
<span class="low">{{ self.low }}</span> <span class="low">{{ self.low }}</span>
......
<div class="quizz-tip"> <p>{{ self.content }}</p>
<strong>
To the question <em>"{{ self.question }}"</em>,
{% if self.student_choice %}
you answered <em>"{{ self.student_choice }}"</em>.
{% else %}
you have not provided an answer.
{% endif %}
</strong>
<p>{{ self.tip }}</p>
</div>
<div class="quizz-tip">
<strong>
To the question <em>"{{ self.question }}"</em>,
{% if submission %}
you answered <em>"{{ submission }}"</em>.
{% else %}
you have not provided an answer.
{% endif %}
</strong>
{% for tip in tips %}
{{ tip }}
{% endfor %}
</div>
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
<quizz name="goal-important" type="rating-unsure" low="Not at all important to me" high="Very important to me"> <quizz name="goal-important" type="rating-unsure" low="Not at all important to me" high="Very important to me">
<question>How important is it to you?</question> <question>How important is it to you?</question>
<tip reject="1 2 3">Text on why it is important to choose a goal that is important to you and instructions to go back and revise your goal to make it meet the criteria.</tip> <tip reject="1,2,3">Text on why it is important to choose a goal that is important to you and instructions to go back and revise your goal to make it meet the criteria.</tip>
<tip reject="unsure">Help on what 'important' means.</tip> <tip reject="unsure">Help on what 'important' means.</tip>
</quizz> </quizz>
......
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