diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py index 36754815f9..c7bcf93d4c 100644 --- a/cms/djangoapps/contentstore/views/item.py +++ b/cms/djangoapps/contentstore/views/item.py @@ -47,6 +47,7 @@ from contentstore.views.helpers import ( from contentstore.views.preview import get_preview_fragment from edxmako.shortcuts import render_to_string from models.settings.course_grading import CourseGradingModel +from openedx.core.djangoapps.waffle_utils import WaffleSwitch from openedx.core.lib.gating import api as gating_api from openedx.core.lib.xblock_utils import request_token, wrap_xblock from static_replace import replace_static_urls @@ -1185,7 +1186,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F elif xblock.category == 'chapter': xblock_info.update({ 'highlights': xblock.highlights, - 'highlights_enabled': settings.FEATURES.get('ENABLE_SECTION_HIGHLIGHTS', False), + 'highlights_enabled': highlights_setting().is_enabled(), }) # update xblock_info with special exam information if the feature flag is enabled @@ -1247,6 +1248,12 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F return xblock_info +def highlights_setting(): + namespace = u'dynamic_pacing' + switch = u'studio_course_update' + return WaffleSwitch(namespace, switch) + + def add_container_page_publishing_info(xblock, xblock_info): # pylint: disable=invalid-name """ Adds information about the xblock's publish state to the supplied diff --git a/cms/djangoapps/contentstore/views/tests/test_item.py b/cms/djangoapps/contentstore/views/tests/test_item.py index c646a5b879..683c08c554 100644 --- a/cms/djangoapps/contentstore/views/tests/test_item.py +++ b/cms/djangoapps/contentstore/views/tests/test_item.py @@ -33,7 +33,8 @@ from contentstore.views.item import ( _get_source_index, _xblock_type_and_display_name, add_container_page_publishing_info, - create_xblock_info + create_xblock_info, + highlights_setting, ) from lms_xblock.mixin import NONSENSICAL_ACCESS_RESTRICTION from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration @@ -2571,6 +2572,12 @@ class TestXBlockInfo(ItemTest): self.assertEqual(xblock_info['start'], DEFAULT_START_DATE.strftime('%Y-%m-%dT%H:%M:%SZ')) + def test_highlights_enabled(self): + chapter = modulestore().get_item(self.chapter.location) + with highlights_setting().override(): + xblock_info = create_xblock_info(chapter) + self.assertTrue(xblock_info['highlights_enabled']) + def validate_course_xblock_info(self, xblock_info, has_child_info=True, course_outline=False): """ Validate that the xblock info is correct for the test course. @@ -2598,6 +2605,7 @@ class TestXBlockInfo(ItemTest): self.assertEqual(xblock_info['due'], None) self.assertEqual(xblock_info['format'], None) self.assertEqual(xblock_info['highlights'], self.chapter.highlights) + self.assertFalse(xblock_info['highlights_enabled']) # Finally, validate the entire response for consistency self.validate_xblock_info_consistency(xblock_info, has_child_info=has_child_info) diff --git a/cms/envs/common.py b/cms/envs/common.py index c7e3731d55..5c2adfcf06 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -265,9 +265,6 @@ FEATURES = { # Whether archived courses (courses with end dates in the past) should be # shown in Studio in a separate list. 'ENABLE_SEPARATE_ARCHIVED_COURSES': True, - - # Whether section-level highlights are enabled on the platform. - 'ENABLE_SECTION_HIGHLIGHTS': False, } ENABLE_JASMINE = False diff --git a/cms/envs/test.py b/cms/envs/test.py index cc844bfc06..051b10c293 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -326,8 +326,6 @@ SEARCH_ENGINE = "search.tests.mock_search_engine.MockSearchEngine" FEATURES['ENABLE_ENROLLMENT_TRACK_USER_PARTITION'] = True -FEATURES['ENABLE_SECTION_HIGHLIGHTS'] = True - ########################## AUTHOR PERMISSION ####################### FEATURES['ENABLE_CREATOR_GROUP'] = False diff --git a/openedx/core/djangoapps/waffle_utils/__init__.py b/openedx/core/djangoapps/waffle_utils/__init__.py index c0a8b2da64..90b4a2d320 100644 --- a/openedx/core/djangoapps/waffle_utils/__init__.py +++ b/openedx/core/djangoapps/waffle_utils/__init__.py @@ -48,10 +48,14 @@ To test WaffleSwitchNamespace, use the provided context managers. For example: import logging from abc import ABCMeta from contextlib import contextmanager + +import six from opaque_keys.edx.keys import CourseKey -from request_cache import get_cache as get_request_cache, get_request from waffle import flag_is_active, switch_is_active +from request_cache import get_cache as get_request_cache +from request_cache import get_request + log = logging.getLogger(__name__) @@ -165,6 +169,31 @@ class WaffleSwitchNamespace(WaffleNamespace): return self._get_request_cache().setdefault('switches', {}) +class WaffleSwitch(object): + """ + Represents a single waffle switch, using a cached namespace. + """ + def __init__(self, waffle_namespace, switch_name): + """ + Arguments: + waffle_namespace (WaffleSwitchNamespace | String): Namespace for this switch. + switch_name (String): The name of the switch (without namespacing). + """ + if isinstance(waffle_namespace, six.string_types): + waffle_namespace = WaffleSwitchNamespace(name=waffle_namespace) + + self.waffle_namespace = waffle_namespace + self.switch_name = switch_name + + def is_enabled(self): + return self.waffle_namespace.is_enabled(self.switch_name) + + @contextmanager + def override(self, active=True): + with self.waffle_namespace.override(self.switch_name, active): + yield + + class WaffleFlagNamespace(WaffleNamespace): """ Provides a single namespace for a set of waffle flags.