Switch disabling of XBlocks to XBlockConfiguration.
Also allows dynamic updates. TNL-4668
This commit is contained in:
@@ -41,16 +41,6 @@ class XBlockDisableConfig(ConfigurationModel):
|
||||
|
||||
return block_type in config.disabled_blocks.split()
|
||||
|
||||
@classmethod
|
||||
def disabled_block_types(cls):
|
||||
""" Return list of disabled xblock types. """
|
||||
|
||||
config = cls.current()
|
||||
if not config.enabled:
|
||||
return ()
|
||||
|
||||
return config.disabled_blocks.split()
|
||||
|
||||
@classmethod
|
||||
def disabled_create_block_types(cls):
|
||||
""" Return list of deprecated XBlock types. Merges types in settings file and field. """
|
||||
|
||||
@@ -19,6 +19,7 @@ from django.conf import settings
|
||||
if not settings.configured:
|
||||
settings.configure()
|
||||
|
||||
from django.db.models.signals import post_save
|
||||
from django.core.cache import caches, InvalidCacheBackendError
|
||||
import django.dispatch
|
||||
import django.utils
|
||||
@@ -49,9 +50,11 @@ except ImportError:
|
||||
HAS_USER_SERVICE = False
|
||||
|
||||
try:
|
||||
from xblock_django.models import XBlockDisableConfig
|
||||
from xblock_django.api import disabled_xblocks
|
||||
from xblock_django.models import XBlockConfiguration
|
||||
except ImportError:
|
||||
XBlockDisableConfig = None
|
||||
disabled_xblocks = None
|
||||
XBlockConfiguration = None
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
ASSET_IGNORE_REGEX = getattr(settings, "ASSET_IGNORE_REGEX", r"(^\._.*$)|(^\.DS_Store$)|(^.*~$)")
|
||||
@@ -188,8 +191,8 @@ def create_modulestore_instance(
|
||||
if 'read_preference' in doc_store_config:
|
||||
doc_store_config['read_preference'] = getattr(ReadPreference, doc_store_config['read_preference'])
|
||||
|
||||
if XBlockDisableConfig and settings.FEATURES.get('ENABLE_DISABLING_XBLOCK_TYPES', False):
|
||||
disabled_xblock_types = XBlockDisableConfig.disabled_block_types()
|
||||
if disabled_xblocks:
|
||||
disabled_xblock_types = [block.name for block in disabled_xblocks()]
|
||||
else:
|
||||
disabled_xblock_types = ()
|
||||
|
||||
@@ -252,6 +255,17 @@ def clear_existing_modulestores():
|
||||
_MIXED_MODULESTORE = None
|
||||
|
||||
|
||||
if XBlockConfiguration and disabled_xblocks:
|
||||
@django.dispatch.receiver(post_save, sender=XBlockConfiguration)
|
||||
def reset_disabled_xblocks(sender, instance, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
If XBlockConfiguation and disabled_xblocks are available, register a signal handler
|
||||
to update disabled_xblocks on model changes.
|
||||
"""
|
||||
disabled_xblock_types = [block.name for block in disabled_xblocks()]
|
||||
modulestore().disabled_xblock_types = disabled_xblock_types
|
||||
|
||||
|
||||
class ModuleI18nService(object):
|
||||
"""
|
||||
Implement the XBlock runtime "i18n" service.
|
||||
|
||||
@@ -185,6 +185,25 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
|
||||
self.mappings[course_key] = store
|
||||
self.modulestores.append(store)
|
||||
|
||||
@property
|
||||
def disabled_xblock_types(self):
|
||||
"""
|
||||
Returns the list of disabled xblock types.
|
||||
"""
|
||||
return None if not hasattr(self, "_disabled_xblock_types") else self._disabled_xblock_types
|
||||
|
||||
@disabled_xblock_types.setter
|
||||
def disabled_xblock_types(self, value):
|
||||
"""
|
||||
Sets the list of disabled xblock types, and propagates down
|
||||
to child modulestores if available.
|
||||
"""
|
||||
self._disabled_xblock_types = value # pylint: disable=attribute-defined-outside-init
|
||||
|
||||
if hasattr(self, 'modulestores'):
|
||||
for store in self.modulestores:
|
||||
store.disabled_xblock_types = value
|
||||
|
||||
def _clean_locator_for_mapping(self, locator):
|
||||
"""
|
||||
In order for mapping to work, the locator must be minimal--no version, no branch--
|
||||
|
||||
@@ -59,6 +59,7 @@ from openedx.core.djangoapps.credit.api import (
|
||||
set_credit_requirements,
|
||||
set_credit_requirement_status
|
||||
)
|
||||
from xblock_django.models import XBlockConfiguration
|
||||
|
||||
from edx_proctoring.api import (
|
||||
create_exam,
|
||||
@@ -2232,7 +2233,22 @@ class TestDisabledXBlockTypes(ModuleStoreTestCase):
|
||||
def test_get_item(self, default_ms):
|
||||
with self.store.default_store(default_ms):
|
||||
course = CourseFactory()
|
||||
for block_type in ('video',):
|
||||
item = ItemFactory(category=block_type, parent=course)
|
||||
item = self.store.get_item(item.scope_ids.usage_id)
|
||||
self.assertEqual(item.__class__.__name__, 'RawDescriptorWithMixins')
|
||||
self._verify_descriptor('video', course, 'RawDescriptorWithMixins')
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_dynamic_updates(self, default_ms):
|
||||
"""Tests that the list of disabled xblocks can dynamically update."""
|
||||
with self.store.default_store(default_ms):
|
||||
course = CourseFactory()
|
||||
self._verify_descriptor('problem', course, 'CapaDescriptorWithMixins')
|
||||
XBlockConfiguration(name='problem', enabled=False).save()
|
||||
self._verify_descriptor('problem', course, 'RawDescriptorWithMixins')
|
||||
|
||||
def _verify_descriptor(self, category, course, descriptor):
|
||||
"""
|
||||
Helper method that gets an item with the specified category from the
|
||||
modulestore and verifies that it has the expected descriptor name.
|
||||
"""
|
||||
item = ItemFactory(category=category, parent=course)
|
||||
item = self.store.get_item(item.scope_ids.usage_id)
|
||||
self.assertEqual(item.__class__.__name__, descriptor)
|
||||
|
||||
@@ -340,9 +340,6 @@ FEATURES = {
|
||||
# Enable OpenBadge support. See the BADGR_* settings later in this file.
|
||||
'ENABLE_OPENBADGES': False,
|
||||
|
||||
# The block types to disable need to be specified in "x block disable config" in django admin.
|
||||
'ENABLE_DISABLING_XBLOCK_TYPES': True,
|
||||
|
||||
# Enable LTI Provider feature.
|
||||
'ENABLE_LTI_PROVIDER': False,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user