Skip to content

Commit b801d98

Browse files
abodacsAgrendalath
andauthored
feat: render HTML in explanations (#295)
It makes them consistent with other XBlock fields. Co-authored-by: Agrendalath <piotr@surowiec.it>
1 parent 2da2b59 commit b801d98

File tree

7 files changed

+38
-10
lines changed

7 files changed

+38
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ __pycache__/
77

88
# Distribution / packaging
99
.Python
10+
venv/
1011
env/
1112
build/
1213
develop-eggs/

Changelog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
Drag and Drop XBlock changelog
22
==============================
33

4+
Version 2.4.2 (2022-10-13)
5+
---------------------------
6+
7+
* Support HTML in explanations.
8+
49
Version 2.4.1 (2022-10-06)
510
---------------------------
611
* Remove dots on feedback and moves final feedback to end and set bold text on assessment mode.

drag_and_drop_v2/drag_and_drop_v2.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
import six.moves.urllib.error # pylint: disable=import-error
1515
import six.moves.urllib.parse # pylint: disable=import-error
1616
import six.moves.urllib.request # pylint: disable=import-error
17-
import pkg_resources
1817
import six
18+
import pkg_resources
1919
import webob
2020

2121
from django.utils import translation
@@ -44,6 +44,7 @@
4444

4545
# pylint: disable=bad-continuation
4646
@XBlock.wants('settings')
47+
@XBlock.wants('replace_urls')
4748
@XBlock.needs('i18n')
4849
class DragAndDropBlock(
4950
ScorableXBlockMixin,
@@ -620,8 +621,21 @@ def show_answer(self, data, suffix=''):
620621

621622
answer = self._get_correct_state()
622623

623-
answer['explanation'] = self.data.get('explanation', '').strip()
624+
if explanation := self.data.get('explanation', '').strip():
625+
if replace_urls_service := self.runtime.service(self, 'replace_urls'):
626+
explanation = replace_urls_service.replace_urls(explanation)
624627

628+
# pylint: disable=fixme
629+
# TODO: No longer needed after Maple.
630+
else:
631+
try:
632+
explanation = self.runtime.replace_urls(explanation)
633+
explanation = self.runtime.replace_course_urls(explanation)
634+
explanation = self.runtime.replace_jump_to_id_urls(explanation)
635+
except (TypeError, AttributeError):
636+
logger.debug('Unable to perform URL substitution on the explanation: %s', explanation)
637+
638+
answer['explanation'] = explanation
625639
return answer
626640

627641
@XBlock.json_handler

drag_and_drop_v2/public/js/drag_and_drop.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ function DragAndDropTemplates(configuration) {
339339
h('span', [
340340
h('.detailed-solution', [
341341
h('p', gettext('Explanation')),
342-
h('p', gettext(ctx.explanation)),
342+
h('p', {innerHTML: gettext(ctx.explanation)}),
343343
])
344344
])
345345
])

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def package_data(pkg, root_list):
2323

2424
setup(
2525
name='xblock-drag-and-drop-v2',
26-
version='2.4.1',
26+
version='2.4.2',
2727
description='XBlock - Drag-and-Drop v2',
2828
packages=['drag_and_drop_v2'],
2929
install_requires=[

tests/integration/test_custom_data_render.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,5 @@ def test_html_title_renders_properly(self):
6363
Tests HTML titles are rendered properly
6464
"""
6565
zones = self._get_zones()
66-
self.assertEqual(u'Zone\ndroppable\nNo items placed here', zones[0].text)
67-
self.assertNotEqual(u'Zone <sup>-1</sup>\ndroppable\nNo items placed here', zones[0].text)
66+
self.assertEqual('Zone\ndroppable\nNo items placed here', zones[0].text)
67+
self.assertNotEqual('Zone <sup>-1</sup>\ndroppable\nNo items placed here', zones[0].text)

tests/integration/test_interaction_assessment.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -474,13 +474,18 @@ def load_scenario(self, explanation_text: str, scenario_id: int):
474474
self._add_scenario(scenario_page_id, scenario_page_title, scenario_xml)
475475
self._page = self.go_to_page(scenario_page_title)
476476

477+
@staticmethod
478+
def _get_explanation_html(explanation: str) -> str:
479+
return f'<span><div class="detailed-solution"><p>Explanation</p><p>{explanation}</p></div></span>'
480+
477481
@ddt.data(
478-
(1, "This is an explanation.", True),
479-
(2, " ", False),
480-
(3, None, False),
482+
(1, "This is an explanation.", True, "Explanation\nThis is an explanation."),
483+
(2, " ", False, None),
484+
(3, None, False, None),
485+
(4, "12m<sup>2</sup>", True, "Explanation\n12m2"),
481486
)
482487
@ddt.unpack
483-
def test_explanation(self, scenario_id: int, explanation: str, should_display: bool):
488+
def test_explanation(self, scenario_id: int, explanation: str, should_display: bool, rendered_explanation: str):
484489
"""
485490
Test that the "Explanation" is displayed after the "Show Answer" button is clicked.
486491
The docstring of the class explains when the explanation should be visible.
@@ -498,3 +503,6 @@ def test_explanation(self, scenario_id: int, explanation: str, should_display: b
498503

499504
explanation_block = self._get_explanation()
500505
self.assertEqual(explanation_block.is_displayed(), should_display)
506+
if should_display:
507+
self.assertEqual(rendered_explanation, explanation_block.text)
508+
self.assertEqual(self._get_explanation_html(explanation), explanation_block.get_attribute('innerHTML'))

0 commit comments

Comments
 (0)