Merge pull request #27961 from edx/saad/TNL-8389
feat: Add CourseWaffleFlag for overriding course discussion settings for legacy experience.
This commit is contained in:
@@ -67,19 +67,3 @@ REDIRECT_TO_LIBRARY_AUTHORING_MICROFRONTEND = LegacyWaffleFlag(
|
||||
flag_name='library_authoring_mfe',
|
||||
module_name=__name__,
|
||||
)
|
||||
|
||||
|
||||
# .. toggle_name: studio.pages_and_resources_mfe
|
||||
# .. toggle_implementation: CourseWaffleFlag
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Waffle flag to link existing studio views to the new Pages and Resources experience.
|
||||
# .. toggle_use_cases: temporary, open_edx
|
||||
# .. toggle_creation_date: 2021-05-24
|
||||
# .. toggle_target_removal_date: 2021-12-31
|
||||
# .. toggle_warnings: Also set settings.COURSE_AUTHORING_MICROFRONTEND_URL.
|
||||
# .. toggle_tickets: None
|
||||
ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND = CourseWaffleFlag(
|
||||
waffle_namespace=waffle_flags(),
|
||||
flag_name='pages_and_resources_mfe',
|
||||
module_name=__name__,
|
||||
)
|
||||
|
||||
@@ -34,6 +34,10 @@ from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRol
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from common.djangoapps.util import milestones_helpers
|
||||
from common.djangoapps.xblock_django.models import XBlockStudioConfigurationFlag
|
||||
from openedx.core.djangoapps.discussions.config.waffle import (
|
||||
ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND,
|
||||
OVERRIDE_DISCUSSION_LEGACY_SETTINGS_FLAG
|
||||
)
|
||||
from openedx.core.djangoapps.models.course_details import CourseDetails
|
||||
from xmodule.fields import Date
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
@@ -93,6 +97,7 @@ class CourseSettingsEncoderTest(CourseTestCase):
|
||||
self.assertEqual(jsondetails['string'], 'string')
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class CourseAdvanceSettingViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
"""
|
||||
Tests for AdvanceSettings View.
|
||||
@@ -119,6 +124,27 @@ class CourseAdvanceSettingViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
self.assertEqual(settings_fields["display_name"], "Mobile Course Available")
|
||||
self.assertEqual(settings_fields["deprecated"], True)
|
||||
|
||||
@ddt.data(
|
||||
(False, False, True),
|
||||
(True, False, False),
|
||||
(True, True, True),
|
||||
(False, True, True)
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_discussion_fields_available(self, is_pages_and_resources_enabled,
|
||||
is_legacy_discussion_setting_enabled, fields_visible):
|
||||
"""
|
||||
Test to check the availability of discussion related fields when relevant flags are enabled
|
||||
"""
|
||||
|
||||
with override_waffle_flag(ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND, is_pages_and_resources_enabled):
|
||||
with override_waffle_flag(OVERRIDE_DISCUSSION_LEGACY_SETTINGS_FLAG, is_legacy_discussion_setting_enabled):
|
||||
response = self.client.get_html(self.course_setting_url).content.decode('utf-8')
|
||||
self.assertEqual('allow_anonymous' in response, fields_visible)
|
||||
self.assertEqual('allow_anonymous_to_peers' in response, fields_visible)
|
||||
self.assertEqual('discussion_blackouts' in response, fields_visible)
|
||||
self.assertEqual('discussion_topics' in response, fields_visible)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
|
||||
@@ -14,11 +14,11 @@ from opaque_keys.edx.keys import CourseKey, UsageKey
|
||||
from opaque_keys.edx.locator import LibraryLocator
|
||||
from pytz import UTC
|
||||
|
||||
from cms.djangoapps.contentstore.config.waffle import ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND
|
||||
from cms.djangoapps.contentstore.toggles import exam_setting_view_enabled
|
||||
from common.djangoapps.student import auth
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole
|
||||
from openedx.core.djangoapps.discussions.config.waffle import ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND
|
||||
from openedx.core.djangoapps.django_comment_common.models import assign_default_role
|
||||
from openedx.core.djangoapps.django_comment_common.utils import seed_permissions_roles
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
|
||||
@@ -14,6 +14,7 @@ from xblock.fields import Scope
|
||||
|
||||
from cms.djangoapps.contentstore import toggles
|
||||
from common.djangoapps.xblock_django.models import XBlockStudioConfigurationFlag
|
||||
from openedx.core.djangoapps.discussions.config.waffle_utils import legacy_discussion_experience_enabled
|
||||
from openedx.core.lib.teams_config import TeamsetType
|
||||
from openedx.features.course_experience import COURSE_ENABLE_UNENROLLED_ACCESS_FLAG
|
||||
from xmodule.modulestore.django import modulestore
|
||||
@@ -141,6 +142,12 @@ class CourseMetadata:
|
||||
if not settings.PROCTORING_BACKENDS or settings.PROCTORING_BACKENDS.get('proctortrack') is None:
|
||||
exclude_list.append('proctoring_escalation_email')
|
||||
|
||||
if not legacy_discussion_experience_enabled(course_key):
|
||||
exclude_list.append('discussion_blackouts')
|
||||
exclude_list.append('allow_anonymous')
|
||||
exclude_list.append('allow_anonymous_to_peers')
|
||||
exclude_list.append('discussion_topics')
|
||||
|
||||
return exclude_list
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
Unit tests for instructor_dashboard.py.
|
||||
"""
|
||||
|
||||
|
||||
import datetime
|
||||
import re
|
||||
from unittest.mock import patch
|
||||
@@ -30,6 +29,11 @@ from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
|
||||
from lms.djangoapps.grades.config.waffle import WRITABLE_GRADEBOOK, waffle_flags
|
||||
from lms.djangoapps.instructor.toggles import DATA_DOWNLOAD_V2
|
||||
from lms.djangoapps.instructor.views.gradebook_api import calculate_page_info
|
||||
from openedx.core.djangoapps.course_groups.cohorts import set_course_cohorted
|
||||
from openedx.core.djangoapps.discussions.config.waffle import (
|
||||
ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND,
|
||||
OVERRIDE_DISCUSSION_LEGACY_SETTINGS_FLAG
|
||||
)
|
||||
from openedx.core.djangoapps.site_configuration.models import SiteConfiguration
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase
|
||||
@@ -104,6 +108,7 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT
|
||||
"""
|
||||
Verify that the instructor tab appears for staff only.
|
||||
"""
|
||||
|
||||
def has_instructor_tab(user, course):
|
||||
"""Returns true if the "Instructor" tab is shown."""
|
||||
tabs = get_course_tab_list(user, course)
|
||||
@@ -135,6 +140,62 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT
|
||||
)
|
||||
assert has_instructor_tab(org_researcher, self.course)
|
||||
|
||||
@ddt.data(
|
||||
('staff', False, False, True),
|
||||
('staff', True, False, False),
|
||||
('staff', True, True, True),
|
||||
('staff', False, True, True),
|
||||
('instructor', False, False, True),
|
||||
('instructor', True, False, False),
|
||||
('instructor', True, True, True),
|
||||
('instructor', False, True, True)
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_discussion_tab_for_course_staff_role(self, access_role, is_pages_and_resources_enabled,
|
||||
is_legacy_discussion_setting_enabled, is_discussion_tab_available):
|
||||
"""
|
||||
Verify that the Discussion tab is available for course for course staff role.
|
||||
"""
|
||||
discussion_section = ('<li class="nav-item"><button type="button" class="btn-link discussions_management" '
|
||||
'data-section="discussions_management">Discussions</button></li>')
|
||||
|
||||
with override_waffle_flag(ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND, is_pages_and_resources_enabled):
|
||||
with override_waffle_flag(OVERRIDE_DISCUSSION_LEGACY_SETTINGS_FLAG, is_legacy_discussion_setting_enabled):
|
||||
user = UserFactory.create()
|
||||
CourseAccessRoleFactory(
|
||||
course_id=self.course.id,
|
||||
user=user,
|
||||
role=access_role,
|
||||
org=self.course.id.org
|
||||
)
|
||||
set_course_cohorted(self.course.id, True)
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
response = self.client.get(self.url).content.decode('utf-8')
|
||||
self.assertEqual(discussion_section in response, is_discussion_tab_available)
|
||||
|
||||
@ddt.data(
|
||||
(False, False, True),
|
||||
(True, False, False),
|
||||
(True, True, True),
|
||||
(False, True, True),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_discussion_tab_for_global_user(self, is_pages_and_resources_enabled,
|
||||
is_legacy_discussion_setting_enabled, is_discussion_tab_available):
|
||||
"""
|
||||
Verify that the Discussion tab is available for course for global user.
|
||||
"""
|
||||
discussion_section = ('<li class="nav-item"><button type="button" class="btn-link discussions_management" '
|
||||
'data-section="discussions_management">Discussions</button></li>')
|
||||
|
||||
with override_waffle_flag(ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND, is_pages_and_resources_enabled):
|
||||
with override_waffle_flag(OVERRIDE_DISCUSSION_LEGACY_SETTINGS_FLAG, is_legacy_discussion_setting_enabled):
|
||||
user = UserFactory.create(is_staff=True)
|
||||
set_course_cohorted(self.course.id, True)
|
||||
self.client.login(username=user.username, password='test')
|
||||
response = self.client.get(self.url).content.decode('utf-8')
|
||||
self.assertEqual(discussion_section in response, is_discussion_tab_available)
|
||||
|
||||
@ddt.data(
|
||||
('staff', False, False),
|
||||
('instructor', False, False),
|
||||
@@ -154,7 +215,7 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT
|
||||
download_section = '<li class="nav-item"><button type="button" class="btn-link data_download" ' \
|
||||
'data-section="data_download">Data Download</button></li>'
|
||||
if waffle_status:
|
||||
download_section = '<li class="nav-item"><button type="button" class="btn-link data_download_2" '\
|
||||
download_section = '<li class="nav-item"><button type="button" class="btn-link data_download_2" ' \
|
||||
'data-section="data_download_2">Data Download</button></li>'
|
||||
user = UserFactory.create(is_staff=access_role == 'global_staff')
|
||||
CourseAccessRoleFactory(
|
||||
@@ -438,7 +499,7 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_ccx_coaches_option_on_admin_list_management_instructor(
|
||||
self, ccx_feature_flag, enable_ccx, expected_result
|
||||
self, ccx_feature_flag, enable_ccx, expected_result
|
||||
):
|
||||
"""
|
||||
Test whether the "CCX Coaches" option is visible or hidden depending on the value of course.enable_ccx.
|
||||
|
||||
@@ -52,6 +52,7 @@ from lms.djangoapps.courseware.module_render import get_module_by_usage_id
|
||||
from lms.djangoapps.discussion.django_comment_client.utils import available_division_schemes, has_forum_access
|
||||
from lms.djangoapps.grades.api import is_writable_gradebook_enabled
|
||||
from openedx.core.djangoapps.course_groups.cohorts import DEFAULT_COHORT_NAME, get_course_cohorts, is_course_cohorted
|
||||
from openedx.core.djangoapps.discussions.config.waffle_utils import legacy_discussion_experience_enabled
|
||||
from openedx.core.djangoapps.django_comment_common.models import FORUM_ROLE_ADMINISTRATOR, CourseDiscussionSettings
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.verified_track_content.models import VerifiedTrackCohortedCourse
|
||||
@@ -133,13 +134,17 @@ def instructor_dashboard_2(request, course_id): # lint-amnesty, pylint: disable
|
||||
|
||||
sections = []
|
||||
if access['staff']:
|
||||
sections.extend([
|
||||
sections_content = [
|
||||
_section_course_info(course, access),
|
||||
_section_membership(course, access),
|
||||
_section_cohort_management(course, access),
|
||||
_section_discussions_management(course, access),
|
||||
_section_student_admin(course, access),
|
||||
])
|
||||
]
|
||||
|
||||
if legacy_discussion_experience_enabled(course_key):
|
||||
sections_content.append(_section_discussions_management(course, access))
|
||||
sections.extend(sections_content)
|
||||
|
||||
if access['data_researcher']:
|
||||
sections.append(_section_data_download(course, access))
|
||||
|
||||
|
||||
42
openedx/core/djangoapps/discussions/config/waffle.py
Normal file
42
openedx/core/djangoapps/discussions/config/waffle.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""
|
||||
This module contains various configuration settings via
|
||||
waffle switches for the discussions app.
|
||||
"""
|
||||
|
||||
from edx_toggles.toggles import LegacyWaffleFlagNamespace
|
||||
|
||||
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag
|
||||
|
||||
|
||||
WAFFLE_NAMESPACE = LegacyWaffleFlagNamespace(name='discussions')
|
||||
|
||||
# .. toggle_name: discussions.override_discussion_legacy_settings
|
||||
# .. toggle_implementation: CourseWaffleFlag
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Waffle flag to override visibility of discussion settings for legacy experience.
|
||||
# .. toggle_use_cases: temporary, open_edx
|
||||
# .. toggle_creation_date: 2021-06-15
|
||||
# .. toggle_target_removal_date: 2021-12-31
|
||||
# .. toggle_warnings: When the flag is ON, the discussion settings will be available on legacy experience.
|
||||
# .. toggle_tickets: TNL-8389
|
||||
OVERRIDE_DISCUSSION_LEGACY_SETTINGS_FLAG = CourseWaffleFlag(
|
||||
waffle_namespace=WAFFLE_NAMESPACE,
|
||||
flag_name='override_discussion_legacy_settings',
|
||||
module_name=__name__,
|
||||
)
|
||||
|
||||
|
||||
# .. toggle_name: discussions.pages_and_resources_mfe
|
||||
# .. toggle_implementation: CourseWaffleFlag
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Waffle flag to enable new Pages and Resources experience for course.
|
||||
# .. toggle_use_cases: temporary, open_edx
|
||||
# .. toggle_creation_date: 2021-05-24
|
||||
# .. toggle_target_removal_date: 2021-12-31
|
||||
# .. toggle_warnings: When the flag is ON, the new experience for Pages and Resources will be enabled.
|
||||
# .. toggle_tickets: TNL-7791
|
||||
ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND = CourseWaffleFlag(
|
||||
waffle_namespace=WAFFLE_NAMESPACE,
|
||||
flag_name='pages_and_resources_mfe',
|
||||
module_name=__name__,
|
||||
)
|
||||
16
openedx/core/djangoapps/discussions/config/waffle_utils.py
Normal file
16
openedx/core/djangoapps/discussions/config/waffle_utils.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
Utils methods for Discussion app waffle flags.
|
||||
"""
|
||||
|
||||
from openedx.core.djangoapps.discussions.config.waffle import (
|
||||
ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND,
|
||||
OVERRIDE_DISCUSSION_LEGACY_SETTINGS_FLAG
|
||||
)
|
||||
|
||||
|
||||
def legacy_discussion_experience_enabled(course_key):
|
||||
"""
|
||||
Checks for relevant flags and returns a boolean whether to show legacy discussion settings or not
|
||||
"""
|
||||
return bool(OVERRIDE_DISCUSSION_LEGACY_SETTINGS_FLAG.is_enabled(course_key) or
|
||||
not ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND.is_enabled(course_key))
|
||||
Reference in New Issue
Block a user