Commit 4360a781 by Don Mitchell

Studio render XBlockAside views

PLAT-280
parent a07df1a6
...@@ -45,7 +45,7 @@ from contentstore.views.helpers import is_unit, xblock_studio_url, xblock_primar ...@@ -45,7 +45,7 @@ from contentstore.views.helpers import is_unit, xblock_studio_url, xblock_primar
from contentstore.views.preview import get_preview_fragment from contentstore.views.preview import get_preview_fragment
from edxmako.shortcuts import render_to_string from edxmako.shortcuts import render_to_string
from models.settings.course_grading import CourseGradingModel from models.settings.course_grading import CourseGradingModel
from cms.lib.xblock.runtime import handler_url, local_resource_url, applicable_aside_types from cms.lib.xblock.runtime import handler_url, local_resource_url
from opaque_keys.edx.keys import UsageKey, CourseKey from opaque_keys.edx.keys import UsageKey, CourseKey
__all__ = ['orphan_handler', 'xblock_handler', 'xblock_view_handler', 'xblock_outline_handler'] __all__ = ['orphan_handler', 'xblock_handler', 'xblock_view_handler', 'xblock_outline_handler']
...@@ -64,7 +64,6 @@ ALWAYS = lambda x: True ...@@ -64,7 +64,6 @@ ALWAYS = lambda x: True
# TODO: Remove this code when Runtimes are no longer created by modulestores # TODO: Remove this code when Runtimes are no longer created by modulestores
xmodule.x_module.descriptor_global_handler_url = handler_url xmodule.x_module.descriptor_global_handler_url = handler_url
xmodule.x_module.descriptor_global_local_resource_url = local_resource_url xmodule.x_module.descriptor_global_local_resource_url = local_resource_url
xmodule.x_module.descriptor_global_applicable_aside_types = applicable_aside_types
def hash_resource(resource): def hash_resource(resource):
......
...@@ -87,7 +87,7 @@ class PreviewModuleSystem(ModuleSystem): # pylint: disable=abstract-method ...@@ -87,7 +87,7 @@ class PreviewModuleSystem(ModuleSystem): # pylint: disable=abstract-method
def handler_url(self, block, handler_name, suffix='', query='', thirdparty=False): def handler_url(self, block, handler_name, suffix='', query='', thirdparty=False):
return reverse('preview_handler', kwargs={ return reverse('preview_handler', kwargs={
'usage_key_string': unicode(block.location), 'usage_key_string': unicode(block.scope_ids.usage_id),
'handler': handler_name, 'handler': handler_name,
'suffix': suffix, 'suffix': suffix,
}) + '?' + query }) + '?' + query
...@@ -96,8 +96,14 @@ class PreviewModuleSystem(ModuleSystem): # pylint: disable=abstract-method ...@@ -96,8 +96,14 @@ class PreviewModuleSystem(ModuleSystem): # pylint: disable=abstract-method
return local_resource_url(block, uri) return local_resource_url(block, uri)
def applicable_aside_types(self, block): def applicable_aside_types(self, block):
# TODO: Implement this to enable XBlockAsides on previews in Studio """
return [] Remove acid_aside
"""
return [
aside_type
for aside_type in super(PreviewModuleSystem, self).applicable_aside_types(block)
if aside_type != 'acid_aside'
]
class StudioUserService(object): class StudioUserService(object):
......
...@@ -9,6 +9,10 @@ from student.tests.factories import UserFactory ...@@ -9,6 +9,10 @@ from student.tests.factories import UserFactory
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from contentstore.views.preview import get_preview_fragment from contentstore.views.preview import get_preview_fragment
from xmodule.modulestore import ModuleStoreEnum
from xblock.core import XBlockAside
from xmodule.modulestore.tests.test_asides import AsideTestType
import re
class GetPreviewHtmlTestCase(TestCase): class GetPreviewHtmlTestCase(TestCase):
...@@ -19,6 +23,7 @@ class GetPreviewHtmlTestCase(TestCase): ...@@ -19,6 +23,7 @@ class GetPreviewHtmlTestCase(TestCase):
get_preview_fragment via the xblock RESTful API. get_preview_fragment via the xblock RESTful API.
""" """
@XBlockAside.register_temp_plugin(AsideTestType, 'test_aside')
def test_preview_fragment(self): def test_preview_fragment(self):
""" """
Test for calling get_preview_html. Test for calling get_preview_html.
...@@ -26,7 +31,7 @@ class GetPreviewHtmlTestCase(TestCase): ...@@ -26,7 +31,7 @@ class GetPreviewHtmlTestCase(TestCase):
This test used to be specifically about Locators (ensuring that they did not This test used to be specifically about Locators (ensuring that they did not
get translated to Locations). The test now has questionable value. get translated to Locations). The test now has questionable value.
""" """
course = CourseFactory.create() course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split)
html = ItemFactory.create( html = ItemFactory.create(
parent_location=course.location, parent_location=course.location,
category="html", category="html",
...@@ -45,9 +50,13 @@ class GetPreviewHtmlTestCase(TestCase): ...@@ -45,9 +50,13 @@ class GetPreviewHtmlTestCase(TestCase):
html = get_preview_fragment(request, html, context).content html = get_preview_fragment(request, html, context).content
# Verify student view html is returned, and the usage ID is as expected. # Verify student view html is returned, and the usage ID is as expected.
html_pattern = unicode(course.id.make_usage_key('html', 'html_')).replace('html_', r'html_[0-9]*') html_pattern = re.escape(unicode(course.id.make_usage_key('html', 'replaceme'))).replace('replaceme', r'html_[0-9]*')
self.assertRegexpMatches( self.assertRegexpMatches(
html, html,
'data-usage-id="{}"'.format(html_pattern) 'data-usage-id="{}"'.format(html_pattern)
) )
self.assertRegexpMatches(html, '<html>foobar</html>') self.assertRegexpMatches(html, '<html>foobar</html>')
self.assertRegexpMatches(html, r"data-block-type=[\"\']test_aside[\"\']")
self.assertRegexpMatches(html, "Aside rendered")
# Now ensure the acid_aside is not in the result
self.assertNotRegexpMatches(html, r"data-block-type=[\"\']acid_aside[\"\']")
...@@ -33,11 +33,3 @@ def local_resource_url(block, uri): ...@@ -33,11 +33,3 @@ def local_resource_url(block, uri):
'block_type': block.scope_ids.block_type, 'block_type': block.scope_ids.block_type,
'uri': uri, 'uri': uri,
}) })
def applicable_aside_types(block): # pylint: disable=unused-argument
"""
Get the application-relative list of aside types for this type of block.
"""
# TODO: Implement this method to make XBlockAsides for editing views in Studio
return []
...@@ -356,6 +356,10 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin): ...@@ -356,6 +356,10 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
""" """
return xblock._edit_info.get('published_date') return xblock._edit_info.get('published_date')
def applicable_aside_types(self, block):
# "old" mongo does support asides yet
return []
# The only thing using this w/ wildcards is contentstore.mongo for asset retrieval # The only thing using this w/ wildcards is contentstore.mongo for asset retrieval
def location_to_query(location, wildcard=True, tag='i4x'): def location_to_query(location, wildcard=True, tag='i4x'):
......
...@@ -28,7 +28,7 @@ class TestAsidesXmlStore(TestCase): ...@@ -28,7 +28,7 @@ class TestAsidesXmlStore(TestCase):
""" """
Test Asides sourced from xml store Test Asides sourced from xml store
""" """
@patch('xmodule.x_module.descriptor_global_applicable_aside_types', lambda block: ['test_aside']) @patch('xmodule.modulestore.xml.ImportSystem.applicable_aside_types', lambda self, block: ['test_aside'])
@XBlockAside.register_temp_plugin(AsideTestType, 'test_aside') @XBlockAside.register_temp_plugin(AsideTestType, 'test_aside')
def test_xml_aside(self): def test_xml_aside(self):
""" """
......
...@@ -203,6 +203,6 @@ class TestLibraries(MixedSplitTestCase): ...@@ -203,6 +203,6 @@ class TestLibraries(MixedSplitTestCase):
message = u"Hello world" message = u"Hello world"
hello_render = lambda _, context: Fragment(message) hello_render = lambda _, context: Fragment(message)
with patch('xmodule.html_module.HtmlDescriptor.author_view', hello_render, create=True): with patch('xmodule.html_module.HtmlDescriptor.author_view', hello_render, create=True):
with patch('xmodule.x_module.descriptor_global_applicable_aside_types', lambda block: []): with patch('xmodule.x_module.DescriptorSystem.applicable_aside_types', lambda self, block: []):
result = library.render(AUTHOR_VIEW, context) result = library.render(AUTHOR_VIEW, context)
self.assertIn(message, result.content) self.assertIn(message, result.content)
...@@ -1133,15 +1133,6 @@ def descriptor_global_local_resource_url(block, uri): # pylint: disable=invalid ...@@ -1133,15 +1133,6 @@ def descriptor_global_local_resource_url(block, uri): # pylint: disable=invalid
raise NotImplementedError("Applications must monkey-patch this function before using local_resource_url for studio_view") raise NotImplementedError("Applications must monkey-patch this function before using local_resource_url for studio_view")
# pylint: disable=invalid-name
def descriptor_global_applicable_aside_types(block): # pylint: disable=unused-argument
"""
See :meth:`xblock.runtime.Runtime.applicable_aside_types`.
"""
raise NotImplementedError("Applications must monkey-patch this function before using applicable_aside_types"
" from a DescriptorSystem.")
class MetricsMixin(object): class MetricsMixin(object):
""" """
Mixin for adding metric logging for render and handle methods in the DescriptorSystem and ModuleSystem. Mixin for adding metric logging for render and handle methods in the DescriptorSystem and ModuleSystem.
...@@ -1320,14 +1311,11 @@ class DescriptorSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # p ...@@ -1320,14 +1311,11 @@ class DescriptorSystem(MetricsMixin, ConfigurableFragmentWrapper, Runtime): # p
""" """
See :meth:`xblock.runtime.Runtime:applicable_aside_types` for documentation. See :meth:`xblock.runtime.Runtime:applicable_aside_types` for documentation.
""" """
potential_set = set(super(DescriptorSystem, self).applicable_aside_types(block))
if getattr(block, 'xmodule_runtime', None) is not None: if getattr(block, 'xmodule_runtime', None) is not None:
return block.xmodule_runtime.applicable_aside_types(block) application_set = set(block.xmodule_runtime.applicable_aside_types(block))
else: return list(potential_set.intersection(application_set))
# Currently, Modulestore is responsible for instantiating DescriptorSystems return list(potential_set)
# This means that LMS/CMS don't have a way to define a subclass of DescriptorSystem
# that implements the correct get_asides. So, for now, instead, we will reference a
# global function that the application can override.
return descriptor_global_applicable_aside_types(block)
def resource_url(self, resource): def resource_url(self, resource):
""" """
......
...@@ -326,7 +326,7 @@ def _section_data_download(course, access): ...@@ -326,7 +326,7 @@ def _section_data_download(course, access):
def null_applicable_aside_types(block): # pylint: disable=unused-argument def null_applicable_aside_types(block): # pylint: disable=unused-argument
""" """
get_aside method for monkey-patching into descriptor_global_applicable_aside_types get_aside method for monkey-patching into applicable_aside_types
while rendering an HtmlDescriptor for email text editing. This returns while rendering an HtmlDescriptor for email text editing. This returns
an empty list. an empty list.
""" """
...@@ -337,8 +337,8 @@ def _section_send_email(course, access): ...@@ -337,8 +337,8 @@ def _section_send_email(course, access):
""" Provide data for the corresponding bulk email section """ """ Provide data for the corresponding bulk email section """
course_key = course.id course_key = course.id
# Monkey-patch descriptor_global_applicable_aside_types to return no asides for the duration of this render # Monkey-patch applicable_aside_types to return no asides for the duration of this render
with patch('xmodule.x_module.descriptor_global_applicable_aside_types', null_applicable_aside_types): with patch.object(course.runtime, 'applicable_aside_types', null_applicable_aside_types):
# This HtmlDescriptor is only being used to generate a nice text editor. # This HtmlDescriptor is only being used to generate a nice text editor.
html_module = HtmlDescriptor( html_module = HtmlDescriptor(
course.system, course.system,
......
...@@ -9,7 +9,6 @@ from django.core.urlresolvers import reverse ...@@ -9,7 +9,6 @@ from django.core.urlresolvers import reverse
from django.conf import settings from django.conf import settings
from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig
from openedx.core.djangoapps.user_api.api import course_tag as user_course_tag_api from openedx.core.djangoapps.user_api.api import course_tag as user_course_tag_api
from xblock.core import XBlockAside
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.x_module import ModuleSystem from xmodule.x_module import ModuleSystem
from xmodule.partitions.partitions_service import PartitionService from xmodule.partitions.partitions_service import PartitionService
......
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