Merge pull request #25618 from open-craft/symbolist/convert-annotatable-xmodule-to-xblock
[BD-4] Convert Annotatable XModule to XBlock. [SE-3640]
This commit is contained in:
@@ -20,13 +20,13 @@ XMODULES = [
|
||||
"videodev = xmodule.backcompat_module:TranslateCustomTagDescriptor",
|
||||
"videosequence = xmodule.seq_module:SequenceDescriptor",
|
||||
"custom_tag_template = xmodule.raw_module:RawDescriptor",
|
||||
"annotatable = xmodule.annotatable_module:AnnotatableDescriptor",
|
||||
"hidden = xmodule.hidden_module:HiddenDescriptor",
|
||||
"raw = xmodule.raw_module:RawDescriptor",
|
||||
"lti = xmodule.lti_module:LTIDescriptor",
|
||||
]
|
||||
XBLOCKS = [
|
||||
"about = xmodule.html_module:AboutBlock",
|
||||
"annotatable = xmodule.annotatable_module:AnnotatableBlock",
|
||||
"conditional = xmodule.conditional_module:ConditionalBlock",
|
||||
"course_info = xmodule.html_module:CourseInfoBlock",
|
||||
"html = xmodule.html_module:HtmlBlock",
|
||||
|
||||
@@ -5,11 +5,22 @@ import textwrap
|
||||
|
||||
from lxml import etree
|
||||
from pkg_resources import resource_string
|
||||
from web_fragments.fragment import Fragment
|
||||
from xblock.fields import Scope, String
|
||||
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
from xmodule.raw_module import RawDescriptor
|
||||
from xmodule.x_module import XModule
|
||||
from xmodule.editing_module import EditingMixin
|
||||
from xmodule.raw_module import RawMixin
|
||||
from xmodule.util.xmodule_django import add_webpack_to_fragment
|
||||
from xmodule.xml_module import XmlMixin
|
||||
from xmodule.x_module import (
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
shim_xmodule_js,
|
||||
XModuleMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -18,7 +29,20 @@ log = logging.getLogger(__name__)
|
||||
_ = lambda text: text
|
||||
|
||||
|
||||
class AnnotatableFields(object):
|
||||
class AnnotatableBlock(
|
||||
RawMixin,
|
||||
XmlMixin,
|
||||
EditingMixin,
|
||||
XModuleDescriptorToXBlockMixin,
|
||||
XModuleToXBlockMixin,
|
||||
HTMLSnippet,
|
||||
ResourceTemplates,
|
||||
XModuleMixin,
|
||||
):
|
||||
"""
|
||||
Annotatable XBlock.
|
||||
"""
|
||||
|
||||
data = String(
|
||||
help=_("XML data for the annotation"),
|
||||
scope=Scope.content,
|
||||
@@ -47,29 +71,41 @@ class AnnotatableFields(object):
|
||||
default=_('Annotation'),
|
||||
)
|
||||
|
||||
uses_xmodule_styles_setup = True
|
||||
|
||||
class AnnotatableModule(AnnotatableFields, XModule):
|
||||
js = {
|
||||
preview_view_js = {
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/html/display.js'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.js'),
|
||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
],
|
||||
'xmodule_js': resource_string(__name__, 'js/src/xmodule.js'),
|
||||
}
|
||||
js_module_name = "Annotatable"
|
||||
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
|
||||
preview_view_css = {
|
||||
'scss': [
|
||||
resource_string(__name__, 'css/annotatable/display.scss'),
|
||||
],
|
||||
}
|
||||
|
||||
studio_view_js = {
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/raw/edit/xml.js'),
|
||||
],
|
||||
'xmodule_js': resource_string(__name__, 'js/src/xmodule.js'),
|
||||
}
|
||||
studio_view_css = {
|
||||
'scss': [
|
||||
resource_string(__name__, 'css/codemirror/codemirror.scss'),
|
||||
],
|
||||
}
|
||||
studio_js_module_name = "XMLEditingDescriptor"
|
||||
mako_template = "widgets/raw-edit.html"
|
||||
|
||||
icon_class = 'annotatable'
|
||||
resources_dir = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AnnotatableModule, self).__init__(*args, **kwargs)
|
||||
|
||||
xmltree = etree.fromstring(self.data)
|
||||
|
||||
self.instructions = self._extract_instructions(xmltree)
|
||||
self.content = etree.tostring(xmltree, encoding='unicode')
|
||||
self.element_id = self.location.html_id()
|
||||
self.highlight_colors = ['yellow', 'orange', 'purple', 'blue', 'green']
|
||||
HIGHLIGHT_COLORS = ['yellow', 'orange', 'purple', 'blue', 'green']
|
||||
|
||||
def _get_annotation_class_attr(self, index, el):
|
||||
""" Returns a dict with the CSS class attribute to set on the annotation
|
||||
@@ -82,7 +118,7 @@ class AnnotatableModule(AnnotatableFields, XModule):
|
||||
color = el.get(highlight_key)
|
||||
|
||||
if color is not None:
|
||||
if color in self.highlight_colors:
|
||||
if color in self.HIGHLIGHT_COLORS:
|
||||
cls.append('highlight-' + color)
|
||||
attr['_delete'] = highlight_key
|
||||
attr['value'] = ' '.join(cls)
|
||||
@@ -127,7 +163,11 @@ class AnnotatableModule(AnnotatableFields, XModule):
|
||||
|
||||
def _render_content(self):
|
||||
""" Renders annotatable content with annotation spans and returns HTML. """
|
||||
xmltree = etree.fromstring(self.content)
|
||||
|
||||
xmltree = etree.fromstring(self.data)
|
||||
content = etree.tostring(xmltree, encoding='unicode')
|
||||
|
||||
xmltree = etree.fromstring(content)
|
||||
xmltree.tag = 'div'
|
||||
if 'display_name' in xmltree.attrib:
|
||||
del xmltree.attrib['display_name']
|
||||
@@ -150,17 +190,37 @@ class AnnotatableModule(AnnotatableFields, XModule):
|
||||
|
||||
def get_html(self):
|
||||
""" Renders parameters to template. """
|
||||
|
||||
xmltree = etree.fromstring(self.data)
|
||||
instructions = self._extract_instructions(xmltree)
|
||||
|
||||
context = {
|
||||
'display_name': self.display_name_with_default_escaped,
|
||||
'element_id': self.element_id,
|
||||
'instructions_html': self.instructions,
|
||||
'display_name': self.display_name_with_default,
|
||||
'element_id': self.location.html_id(),
|
||||
'instructions_html': instructions,
|
||||
'content_html': self._render_content()
|
||||
}
|
||||
|
||||
return self.system.render_template('annotatable.html', context)
|
||||
|
||||
def student_view(self, context):
|
||||
"""
|
||||
Renders the output that a student will see.
|
||||
"""
|
||||
fragment = Fragment()
|
||||
fragment.add_content(self.get_html())
|
||||
add_webpack_to_fragment(fragment, 'AnnotatableBlockPreview')
|
||||
shim_xmodule_js(fragment, 'Annotatable')
|
||||
|
||||
class AnnotatableDescriptor(AnnotatableFields, RawDescriptor):
|
||||
module_class = AnnotatableModule
|
||||
mako_template = "widgets/raw-edit.html"
|
||||
resources_dir = None
|
||||
return fragment
|
||||
|
||||
def studio_view(self, _context):
|
||||
"""
|
||||
Return the studio view.
|
||||
"""
|
||||
fragment = Fragment(
|
||||
self.system.render_template(self.mako_template, self.get_context())
|
||||
)
|
||||
add_webpack_to_fragment(fragment, 'AnnotatableBlockStudio')
|
||||
shim_xmodule_js(fragment, self.studio_js_module_name)
|
||||
return fragment
|
||||
|
||||
@@ -20,6 +20,7 @@ import six
|
||||
from docopt import docopt
|
||||
from path import Path as path
|
||||
|
||||
from xmodule.annotatable_module import AnnotatableBlock
|
||||
from xmodule.capa_module import ProblemBlock
|
||||
from xmodule.conditional_module import ConditionalBlock
|
||||
from xmodule.html_module import AboutBlock, CourseInfoBlock, HtmlBlock, StaticTabBlock
|
||||
@@ -67,6 +68,7 @@ class VideoBlock(HTMLSnippet):
|
||||
# Should only be used for XModules being converted to XBlocks.
|
||||
XBLOCK_CLASSES = [
|
||||
AboutBlock,
|
||||
AnnotatableBlock,
|
||||
ConditionalBlock,
|
||||
CourseInfoBlock,
|
||||
HtmlBlock,
|
||||
|
||||
@@ -9,12 +9,12 @@ from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
|
||||
from xblock.field_data import DictFieldData
|
||||
from xblock.fields import ScopeIds
|
||||
|
||||
from xmodule.annotatable_module import AnnotatableModule
|
||||
from xmodule.annotatable_module import AnnotatableBlock
|
||||
|
||||
from . import get_test_system
|
||||
|
||||
|
||||
class AnnotatableModuleTestCase(unittest.TestCase):
|
||||
class AnnotatableBlockTestCase(unittest.TestCase):
|
||||
sample_xml = '''
|
||||
<annotatable display_name="Iliad">
|
||||
<instructions>Read the text.</instructions>
|
||||
@@ -33,9 +33,8 @@ class AnnotatableModuleTestCase(unittest.TestCase):
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
super(AnnotatableModuleTestCase, self).setUp()
|
||||
self.annotatable = AnnotatableModule(
|
||||
Mock(),
|
||||
super().setUp()
|
||||
self.annotatable = AnnotatableBlock(
|
||||
get_test_system(),
|
||||
DictFieldData({'data': self.sample_xml}),
|
||||
ScopeIds(None, None, None, BlockUsageLocator(CourseLocator('org', 'course', 'run'), 'category', 'name'))
|
||||
@@ -68,7 +67,7 @@ class AnnotatableModuleTestCase(unittest.TestCase):
|
||||
def test_annotation_class_attr_with_valid_highlight(self):
|
||||
xml = '<annotation title="x" body="y" problem="0" highlight="{highlight}">test</annotation>'
|
||||
|
||||
for color in self.annotatable.highlight_colors:
|
||||
for color in self.annotatable.HIGHLIGHT_COLORS:
|
||||
el = etree.fromstring(xml.format(highlight=color))
|
||||
value = 'annotatable-span highlight highlight-{highlight}'.format(highlight=color)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ from xblock.core import XBlock
|
||||
from xblock.field_data import DictFieldData
|
||||
from xblock.fields import ScopeIds
|
||||
|
||||
from xmodule.annotatable_module import AnnotatableDescriptor
|
||||
from xmodule.annotatable_module import AnnotatableBlock
|
||||
from xmodule.conditional_module import ConditionalBlock
|
||||
from xmodule.course_module import CourseDescriptor
|
||||
from xmodule.html_module import HtmlBlock
|
||||
@@ -55,7 +55,7 @@ from xmodule.x_module import (
|
||||
# to a list of sample field values to test with.
|
||||
# TODO: Add more types of sample data
|
||||
LEAF_XMODULES = {
|
||||
AnnotatableDescriptor: [{}],
|
||||
AnnotatableBlock: [{}],
|
||||
HtmlBlock: [{}],
|
||||
PollDescriptor: [{'display_name': 'Poll Display Name'}],
|
||||
WordCloudBlock: [{}],
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="annotatable-wrapper">
|
||||
<div class="annotatable-header">
|
||||
% if display_name is not UNDEFINED and display_name is not None:
|
||||
<h3 class="hd hd-3 annotatable-title">${display_name}</h3>
|
||||
<h3 class="hd hd-3 annotatable-title">${display_name | h}</h3>
|
||||
% endif
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user