Commit e1863c97 by Xavier Antoviaque

Allow <message> nodes to contain children, especially <html> nodes

parent bd2a6a91
...@@ -2,4 +2,5 @@ from .answer import AnswerBlock ...@@ -2,4 +2,5 @@ from .answer import AnswerBlock
from .dataexport import MentoringDataExportBlock from .dataexport import MentoringDataExportBlock
from .quizz import QuizzBlock, QuizzChoiceBlock, QuizzTipBlock from .quizz import QuizzBlock, QuizzChoiceBlock, QuizzTipBlock
from .mentoring import MentoringBlock from .mentoring import MentoringBlock
from .message import MentoringMessageBlock
from .table import MentoringTableBlock, MentoringTableColumnBlock, MentoringTableColumnHeaderBlock from .table import MentoringTableBlock, MentoringTableColumnBlock, MentoringTableColumnHeaderBlock
...@@ -7,6 +7,7 @@ import logging ...@@ -7,6 +7,7 @@ import logging
from xblock.core import XBlock from xblock.core import XBlock
from xblock.fields import Boolean, Scope, String from xblock.fields import Boolean, Scope, String
from .message import MentoringMessageBlock
from .utils import get_scenarios_from_path, load_resource, render_template, \ from .utils import get_scenarios_from_path, load_resource, render_template, \
XBlockWithChildrenFragmentsMixin XBlockWithChildrenFragmentsMixin
...@@ -31,8 +32,6 @@ class MentoringBlock(XBlock, XBlockWithChildrenFragmentsMixin): ...@@ -31,8 +32,6 @@ class MentoringBlock(XBlock, XBlockWithChildrenFragmentsMixin):
default=False, scope=Scope.user_state) default=False, scope=Scope.user_state)
completed = Boolean(help="Has the student completed this mentoring step?", completed = Boolean(help="Has the student completed this mentoring step?",
default=False, scope=Scope.user_state) default=False, scope=Scope.user_state)
completed_message = String(help="Message to display upon completion",
scope=Scope.content, default="")
next_step = String(help="url_name of the next step the student must complete (global to all blocks)", next_step = String(help="url_name of the next step the student must complete (global to all blocks)",
default='mentoring_first', scope=Scope.preferences) default='mentoring_first', scope=Scope.preferences)
followed_by = String(help="url_name of the step after the current mentoring block in workflow", followed_by = String(help="url_name of the step after the current mentoring block in workflow",
...@@ -43,27 +42,9 @@ class MentoringBlock(XBlock, XBlockWithChildrenFragmentsMixin): ...@@ -43,27 +42,9 @@ class MentoringBlock(XBlock, XBlockWithChildrenFragmentsMixin):
default=True, scope=Scope.content) default=True, scope=Scope.content)
has_children = True has_children = True
@classmethod
def parse_xml(cls, node, runtime, keys):
block = runtime.construct_xblock_from_class(cls, keys)
for child in node:
if child.tag == 'message':
if child.get('type') == 'completed':
block.completed_message = child.text
else:
raise ValueError, u'Invalid value for message type: `{}`'.format(child.get('type'))
else:
block.runtime.add_node_as_child(block, child)
for name, value in node.items():
if name in block.fields:
setattr(block, name, value)
return block
def student_view(self, context): def student_view(self, context):
fragment, named_children = self.get_children_fragment(context, view_name='mentoring_view') fragment, named_children = self.get_children_fragment(context, view_name='mentoring_view',
not_instance_of=MentoringMessageBlock)
fragment.add_content(render_template('templates/html/mentoring.html', { fragment.add_content(render_template('templates/html/mentoring.html', {
'self': self, 'self': self,
...@@ -115,7 +96,7 @@ class MentoringBlock(XBlock, XBlockWithChildrenFragmentsMixin): ...@@ -115,7 +96,7 @@ class MentoringBlock(XBlock, XBlockWithChildrenFragmentsMixin):
completed = completed and child_result['completed'] completed = completed and child_result['completed']
if completed: if completed:
message = u'<div type="completed_message">{}</div>'.format(self.completed_message) message = self.get_message_html('completed')
else: else:
message = '' message = ''
...@@ -133,6 +114,19 @@ class MentoringBlock(XBlock, XBlockWithChildrenFragmentsMixin): ...@@ -133,6 +114,19 @@ class MentoringBlock(XBlock, XBlockWithChildrenFragmentsMixin):
'message': message, 'message': message,
} }
def get_message_fragment(self, message_type):
for child_id in self.children: # pylint: disable=E1101
child = self.runtime.get_block(child_id)
if isinstance(child, MentoringMessageBlock) and child.type == message_type:
return self.runtime.render_child(child, 'mentoring_view', {})
def get_message_html(self, message_type):
fragment = self.get_message_fragment(message_type)
if fragment:
return fragment.body_html()
else:
return ''
@staticmethod @staticmethod
def workbench_scenarios(): def workbench_scenarios():
""" """
......
# -*- coding: utf-8 -*-
# Imports ###########################################################
import logging
from xblock.core import XBlock
from xblock.fields import Scope, String
from xblock.fragment import Fragment
from .utils import render_template, XBlockWithChildrenFragmentsMixin
# Globals ###########################################################
log = logging.getLogger(__name__)
# Classes ###########################################################
class MentoringMessageBlock(XBlock, XBlockWithChildrenFragmentsMixin):
"""
A message which can be conditionally displayed at the mentoring block level,
for example upon completion of the block
"""
content = String(help="Message to display upon completion", scope=Scope.content, default="")
type = String(help="Type of message", scope=Scope.content, default="completed")
has_children = True
def student_view(self, context=None): # pylint: disable=W0613
"""Returns default student view."""
return Fragment(u"<p>I can only appear inside mentoring blocks.</p>")
def mentoring_view(self, context=None):
fragment, named_children = self.get_children_fragment(context, view_name='mentoring_view')
fragment.add_content(render_template('templates/html/message.html', {
'self': self,
'named_children': named_children,
}))
return fragment
...@@ -8,6 +8,7 @@ BLOCKS = [ ...@@ -8,6 +8,7 @@ BLOCKS = [
'header = mentoring:MentoringTableColumnHeaderBlock', 'header = mentoring:MentoringTableColumnHeaderBlock',
'answer = mentoring:AnswerBlock', 'answer = mentoring:AnswerBlock',
'quizz = mentoring:QuizzBlock', 'quizz = mentoring:QuizzBlock',
'message = mentoring:MentoringMessageBlock',
'tip = mentoring:QuizzTipBlock', 'tip = mentoring:QuizzTipBlock',
'choice = mentoring:QuizzChoiceBlock', 'choice = mentoring:QuizzChoiceBlock',
] ]
......
<div class="message {{ self.type }}">
{% for name, c in named_children %}
{{c.body_html|safe}}
{% endfor %}
{% if self.content %}
<p>{{ self.content }}
{% endif %}
</div>
...@@ -114,7 +114,7 @@ class QuizzBlockTest(MentoringBaseTest): ...@@ -114,7 +114,7 @@ class QuizzBlockTest(MentoringBaseTest):
self.assertEqual(len(tips), 3) self.assertEqual(len(tips), 3)
self.assertEqual(tips[0].text, 'To the question "Do you like this quizz?", you answered "Yes".\nGreat!') self.assertEqual(tips[0].text, 'To the question "Do you like this quizz?", you answered "Yes".\nGreat!')
self.assertEqual(tips[1].text, 'To the question "How much do you rate this quizz?", you answered "4".\nI love good grades.') self.assertEqual(tips[1].text, 'To the question "How much do you rate this quizz?", you answered "4".\nI love good grades.')
self.assertEqual(tips[2].text, 'All is good now - congratulations!') self.assertEqual(tips[2].text, 'Congratulations!\nAll is good now...') # Includes child <html>
self.assertEqual(progress.text, '') self.assertEqual(progress.text, '')
self.assertTrue(progress.find_elements_by_css_selector('img')) self.assertTrue(progress.find_elements_by_css_selector('img'))
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
<tip reject="notwant">Your loss!</tip> <tip reject="notwant">Your loss!</tip>
</quizz> </quizz>
<message type="completed">All is good now - congratulations!</message> <message type="completed">
All is good now...
<html><p>Congratulations!</p></html>
</message>
</mentoring> </mentoring>
</vertical> </vertical>
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