diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 1d88cff042a8..1f457929df9c 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -78,6 +78,8 @@ from lms.djangoapps.courseware.tests.helpers import MasqueradeMixin, get_expiration_banner_text, set_preview_mode from lms.djangoapps.courseware.testutils import RenderXBlockTestMixin from lms.djangoapps.courseware.toggles import ( + COURSEWARE_MICROFRONTEND_ALWAYS_OPEN_AUXILIARY_SIDEBAR, + COURSEWARE_MICROFRONTEND_ENABLE_NAVIGATION_SIDEBAR, COURSEWARE_MICROFRONTEND_SEARCH_ENABLED, COURSEWARE_OPTIMIZED_RENDER_XBLOCK, ) @@ -3812,3 +3814,68 @@ def test_is_mfe_search_waffle_disabled(self): self.assertEqual(response.status_code, 200) self.assertEqual(body, {'enabled': False}) + + +class TestCoursewareMFENavigationSidebarTogglesAPI(SharedModuleStoreTestCase): + """ + Tests the endpoint to fetch the Courseware Navigation Sidebar waffle flags status. + """ + + def setUp(self): + super().setUp() + + self.course = CourseFactory.create() + + self.client = APIClient() + self.apiUrl = reverse('courseware_navigation_sidebar_toggles_view', kwargs={'course_id': str(self.course.id)}) + + @override_waffle_flag(COURSEWARE_MICROFRONTEND_ENABLE_NAVIGATION_SIDEBAR, active=True) + @override_waffle_flag(COURSEWARE_MICROFRONTEND_ALWAYS_OPEN_AUXILIARY_SIDEBAR, active=False) + def test_courseware_mfe_navigation_sidebar_enabled_aux_disabled(self): + """ + Getter to check if it is allowed to show the Courseware navigation sidebar to a user + and auxiliary sidebar doesn't open. + """ + response = self.client.get(self.apiUrl, content_type='application/json') + body = json.loads(response.content.decode('utf-8')) + + self.assertEqual(response.status_code, 200) + self.assertEqual(body, {'enable_navigation_sidebar': True, 'always_open_auxiliary_sidebar': False}) + + @override_waffle_flag(COURSEWARE_MICROFRONTEND_ENABLE_NAVIGATION_SIDEBAR, active=True) + @override_waffle_flag(COURSEWARE_MICROFRONTEND_ALWAYS_OPEN_AUXILIARY_SIDEBAR, active=True) + def test_courseware_mfe_navigation_sidebar_enabled_aux_enabled(self): + """ + Getter to check if it is allowed to show the Courseware navigation sidebar to a user + and auxiliary sidebar should always open. + """ + response = self.client.get(self.apiUrl, content_type='application/json') + body = json.loads(response.content.decode('utf-8')) + + self.assertEqual(response.status_code, 200) + self.assertEqual(body, {'enable_navigation_sidebar': True, 'always_open_auxiliary_sidebar': True}) + + @override_waffle_flag(COURSEWARE_MICROFRONTEND_ENABLE_NAVIGATION_SIDEBAR, active=False) + @override_waffle_flag(COURSEWARE_MICROFRONTEND_ALWAYS_OPEN_AUXILIARY_SIDEBAR, active=True) + def test_courseware_mfe_navigation_sidebar_disabled_aux_enabled(self): + """ + Getter to check if the Courseware navigation sidebar shouldn't be shown to a user + and auxiliary sidebar should always open. + """ + response = self.client.get(self.apiUrl, content_type='application/json') + body = json.loads(response.content.decode('utf-8')) + + self.assertEqual(response.status_code, 200) + self.assertEqual(body, {'enable_navigation_sidebar': False, 'always_open_auxiliary_sidebar': True}) + + @override_waffle_flag(COURSEWARE_MICROFRONTEND_ENABLE_NAVIGATION_SIDEBAR, active=False) + @override_waffle_flag(COURSEWARE_MICROFRONTEND_ALWAYS_OPEN_AUXILIARY_SIDEBAR, active=False) + def test_courseware_mfe_navigation_sidebar_toggles_disabled(self): + """ + Getter to check if neither navigation sidebar nor auxiliary sidebar is shown. + """ + response = self.client.get(self.apiUrl, content_type='application/json') + body = json.loads(response.content.decode('utf-8')) + + self.assertEqual(response.status_code, 200) + self.assertEqual(body, {'enable_navigation_sidebar': False, 'always_open_auxiliary_sidebar': False}) diff --git a/lms/djangoapps/courseware/toggles.py b/lms/djangoapps/courseware/toggles.py index ca4584b19ba6..5a6fa6e62c24 100644 --- a/lms/djangoapps/courseware/toggles.py +++ b/lms/djangoapps/courseware/toggles.py @@ -72,9 +72,9 @@ # .. toggle_implementation: WaffleFlag # .. toggle_default: False # .. toggle_description: Disable caching of navigation sidebar blocks on Learning MFE. -# It can be used when caching the structure of large courses for a large number of users -# at the same time can overload the cache storage (memcache or redis). -# .. toggle_use_cases: temporary +# It can be used when caching the structure of large courses for a large number of users +# at the same time can overload the cache storage (memcache or redis). +# .. toggle_use_cases: opt_out, open_edx # .. toggle_creation_date: 2024-03-21 # .. toggle_target_removal_date: None # .. toggle_tickets: FC-0056 @@ -83,6 +83,33 @@ f'{WAFFLE_FLAG_NAMESPACE}.disable_navigation_sidebar_blocks_caching', __name__ ) +# .. toggle_name: courseware.enable_navigation_sidebar +# .. toggle_implementation: WaffleFlag +# .. toggle_default: True +# .. toggle_description: Enable navigation sidebar on Learning MFE +# .. toggle_use_cases: opt_out, open_edx +# .. toggle_creation_date: 2024-03-07 +# .. toggle_target_removal_date: None +# .. toggle_tickets: FC-0056 +COURSEWARE_MICROFRONTEND_ENABLE_NAVIGATION_SIDEBAR = CourseWaffleFlag( + f'{WAFFLE_FLAG_NAMESPACE}.enable_navigation_sidebar', __name__ +) + +# .. toggle_name: courseware.always_open_auxiliary_sidebar +# .. toggle_implementation: WaffleFlag +# .. toggle_default: True +# .. toggle_description: Waffle flag that determines whether the auxiliary sidebar, +# such as discussion or notification, should automatically expand +# on each course unit page within the Learning MFE, without preserving +# the previous state of the sidebar. +# .. toggle_use_cases: temporary +# .. toggle_creation_date: 2024-04-28 +# .. toggle_target_removal_date: 2024-07-28 +# .. toggle_tickets: FC-0056 +COURSEWARE_MICROFRONTEND_ALWAYS_OPEN_AUXILIARY_SIDEBAR = CourseWaffleFlag( + f'{WAFFLE_FLAG_NAMESPACE}.always_open_auxiliary_sidebar', __name__ +) + # .. toggle_name: courseware.mfe_progress_milestones_streak_discount_enabled # .. toggle_implementation: CourseWaffleFlag # .. toggle_default: False diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 4c3fa982ca69..3bf8ae10e8c2 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -88,7 +88,12 @@ from lms.djangoapps.courseware.model_data import FieldDataCache from lms.djangoapps.courseware.models import BaseStudentModuleHistory, StudentModule from lms.djangoapps.courseware.permissions import MASQUERADE_AS_STUDENT, VIEW_COURSE_HOME, VIEW_COURSEWARE -from lms.djangoapps.courseware.toggles import course_is_invitation_only, courseware_mfe_search_is_enabled +from lms.djangoapps.courseware.toggles import ( + course_is_invitation_only, + courseware_mfe_search_is_enabled, + COURSEWARE_MICROFRONTEND_ENABLE_NAVIGATION_SIDEBAR, + COURSEWARE_MICROFRONTEND_ALWAYS_OPEN_AUXILIARY_SIDEBAR, +) from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateClient from lms.djangoapps.courseware.utils import ( _use_new_financial_assistance_flow, @@ -2282,3 +2287,19 @@ def courseware_mfe_search_enabled(request, course_id=None): payload = {"enabled": courseware_mfe_search_is_enabled(course_key) if enabled else False} return JsonResponse(payload) + + +@api_view(['GET']) +def courseware_mfe_navigation_sidebar_toggles(request, course_id=None): + """ + GET endpoint to return navigation sidebar toggles. + """ + try: + course_key = CourseKey.from_string(course_id) if course_id else None + except InvalidKeyError: + return JsonResponse({"error": "Invalid course_id"}) + + return JsonResponse({ + "enable_navigation_sidebar": COURSEWARE_MICROFRONTEND_ENABLE_NAVIGATION_SIDEBAR.is_enabled(course_key), + "always_open_auxiliary_sidebar": COURSEWARE_MICROFRONTEND_ALWAYS_OPEN_AUXILIARY_SIDEBAR.is_enabled(course_key), + }) diff --git a/lms/urls.py b/lms/urls.py index c7a0d49da4d7..2d5d9a200306 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -749,6 +749,11 @@ courseware_views.courseware_mfe_search_enabled, name='courseware_search_enabled_view', ), + re_path( + fr'^courses/{settings.COURSE_ID_PATTERN}/courseware-navigation-sidebar/toggles/$', + courseware_views.courseware_mfe_navigation_sidebar_toggles, + name='courseware_navigation_sidebar_toggles_view', + ), ] urlpatterns += [