Merge pull request #25332 from regisb/regisb/use-settingdict
[BD-21] Use edx-toggle's SettingDictToggle to document setting-based feature toggles
This commit is contained in:
@@ -58,7 +58,6 @@ from util.course import get_link_for_about_page
|
||||
from util.date_utils import get_default_time_display
|
||||
from util.json_request import JsonResponse, JsonResponseBadRequest, expect_json
|
||||
from util.milestones_helpers import (
|
||||
is_entrance_exams_enabled,
|
||||
is_prerequisite_courses_enabled,
|
||||
is_valid_course_key,
|
||||
remove_prerequisite_course,
|
||||
@@ -66,6 +65,7 @@ from util.milestones_helpers import (
|
||||
)
|
||||
from util.organizations_helpers import add_organization_course, get_organization_by_short_name, organizations_enabled
|
||||
from util.string_utils import _has_non_ascii_characters
|
||||
from openedx.core import toggles as core_toggles
|
||||
from xblock_django.api import deprecated_xblocks
|
||||
from xmodule.contentstore.content import StaticContent
|
||||
from xmodule.course_module import DEFAULT_START_DATE, CourseFields
|
||||
@@ -1121,7 +1121,7 @@ def settings_handler(request, course_key_string):
|
||||
'show_min_grade_warning': False,
|
||||
'enrollment_end_editable': enrollment_end_editable,
|
||||
'is_prerequisite_courses_enabled': is_prerequisite_courses_enabled(),
|
||||
'is_entrance_exams_enabled': is_entrance_exams_enabled(),
|
||||
'is_entrance_exams_enabled': core_toggles.ENTRANCE_EXAMS.is_enabled(),
|
||||
'enable_extended_course_details': enable_extended_course_details,
|
||||
'upgrade_deadline': upgrade_deadline,
|
||||
'course_authoring_microfrontend_url': course_authoring_microfrontend_url,
|
||||
@@ -1183,7 +1183,7 @@ def settings_handler(request, course_key_string):
|
||||
# feature-specific settings and handle them accordingly
|
||||
# We have to be careful that we're only executing the following logic if we actually
|
||||
# need to create or delete an entrance exam from the specified course
|
||||
if is_entrance_exams_enabled():
|
||||
if core_toggles.ENTRANCE_EXAMS.is_enabled():
|
||||
course_entrance_exam_present = course_module.entrance_exam_enabled
|
||||
entrance_exam_enabled = request.json.get('entrance_exam_enabled', '') == 'true'
|
||||
ee_min_score_pct = request.json.get('entrance_exam_minimum_score_pct', None)
|
||||
|
||||
@@ -20,6 +20,7 @@ from cms.djangoapps.models.settings.course_metadata import CourseMetadata
|
||||
from openedx.core.djangolib.js_utils import dump_js_escaped_json
|
||||
from student.auth import has_course_author_access
|
||||
from util import milestones_helpers
|
||||
from openedx.core import toggles as core_toggles
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
|
||||
@@ -42,23 +43,21 @@ def _get_default_entrance_exam_minimum_pct():
|
||||
return entrance_exam_minimum_score_pct
|
||||
|
||||
|
||||
def check_feature_enabled(feature_name):
|
||||
def check_entrance_exams_enabled(view_func):
|
||||
"""
|
||||
Ensure the specified feature is turned on. Return an HTTP 400 code if not.
|
||||
Ensure the entrance exams feature is turned on. Return an HTTP 400 code if not.
|
||||
"""
|
||||
def _check_feature_enabled(view_func):
|
||||
def _decorator(request, *args, **kwargs):
|
||||
# Deny access if the entrance exam feature is disabled
|
||||
if not settings.FEATURES.get(feature_name, False):
|
||||
return HttpResponseBadRequest()
|
||||
return view_func(request, *args, **kwargs)
|
||||
return wraps(view_func)(_decorator)
|
||||
return _check_feature_enabled
|
||||
def _decorator(request, *args, **kwargs):
|
||||
# Deny access if the entrance exam feature is disabled
|
||||
if not core_toggles.ENTRANCE_EXAMS.is_enabled():
|
||||
return HttpResponseBadRequest()
|
||||
return view_func(request, *args, **kwargs)
|
||||
return wraps(view_func)(_decorator)
|
||||
|
||||
|
||||
@login_required
|
||||
@ensure_csrf_cookie
|
||||
@check_feature_enabled(feature_name='ENTRANCE_EXAMS')
|
||||
@check_entrance_exams_enabled
|
||||
def entrance_exam(request, course_key_string):
|
||||
"""
|
||||
The restful handler for entrance exams.
|
||||
@@ -105,7 +104,7 @@ def entrance_exam(request, course_key_string):
|
||||
return HttpResponse(status=405)
|
||||
|
||||
|
||||
@check_feature_enabled(feature_name='ENTRANCE_EXAMS')
|
||||
@check_entrance_exams_enabled
|
||||
def create_entrance_exam(request, course_key, entrance_exam_minimum_score_pct):
|
||||
"""
|
||||
api method to create an entrance exam.
|
||||
@@ -186,7 +185,7 @@ def _get_entrance_exam(request, course_key):
|
||||
return HttpResponse(status=404)
|
||||
|
||||
|
||||
@check_feature_enabled(feature_name='ENTRANCE_EXAMS')
|
||||
@check_entrance_exams_enabled
|
||||
def update_entrance_exam(request, course_key, exam_data):
|
||||
"""
|
||||
Operation to update course fields pertaining to entrance exams
|
||||
@@ -200,7 +199,7 @@ def update_entrance_exam(request, course_key, exam_data):
|
||||
CourseMetadata.update_from_dict(metadata, course, request.user)
|
||||
|
||||
|
||||
@check_feature_enabled(feature_name='ENTRANCE_EXAMS')
|
||||
@check_entrance_exams_enabled
|
||||
def delete_entrance_exam(request, course_key):
|
||||
"""
|
||||
api method to delete an entrance exam
|
||||
|
||||
@@ -14,7 +14,7 @@ from xblock.core import XBlock
|
||||
|
||||
from cms.djangoapps.models.settings.course_grading import CourseGradingModel
|
||||
from edxmako.shortcuts import render_to_string
|
||||
from util.milestones_helpers import is_entrance_exams_enabled
|
||||
from openedx.core.toggles import ENTRANCE_EXAMS
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.tabs import StaticTab
|
||||
from xmodule.x_module import DEPRECATION_VSCOMPAT_EVENT
|
||||
@@ -214,7 +214,7 @@ def create_xblock(parent_locator, user, category, display_name, boilerplate=None
|
||||
|
||||
# Entrance Exams: Chapter module positioning
|
||||
child_position = None
|
||||
if is_entrance_exams_enabled():
|
||||
if ENTRANCE_EXAMS.is_enabled():
|
||||
if category == 'chapter' and is_entrance_exam:
|
||||
fields['is_entrance_exam'] = is_entrance_exam
|
||||
fields['in_entrance_exam'] = True # Inherited metadata, all children will have it
|
||||
@@ -238,7 +238,7 @@ def create_xblock(parent_locator, user, category, display_name, boilerplate=None
|
||||
)
|
||||
|
||||
# Entrance Exams: Grader assignment
|
||||
if is_entrance_exams_enabled():
|
||||
if ENTRANCE_EXAMS.is_enabled():
|
||||
course_key = usage_key.course_key
|
||||
course = store.get_course(course_key)
|
||||
if hasattr(course, 'entrance_exam_enabled') and course.entrance_exam_enabled:
|
||||
|
||||
@@ -43,7 +43,7 @@ from static_replace import replace_static_urls
|
||||
from student.auth import has_studio_read_access, has_studio_write_access
|
||||
from util.date_utils import get_default_time_display
|
||||
from util.json_request import JsonResponse, expect_json
|
||||
from util.milestones_helpers import is_entrance_exams_enabled
|
||||
from openedx.core.toggles import ENTRANCE_EXAMS
|
||||
from xblock_django.user_service import DjangoXBlockUserService
|
||||
from xmodule.course_module import DEFAULT_START_DATE
|
||||
from xmodule.library_tools import LibraryToolsService
|
||||
@@ -100,7 +100,7 @@ def _filter_entrance_exam_grader(graders):
|
||||
views/controls like the 'Grade as' dropdown that allows a course author to select
|
||||
the grader type for a given section of a course
|
||||
"""
|
||||
if is_entrance_exams_enabled():
|
||||
if ENTRANCE_EXAMS.is_enabled():
|
||||
graders = [grader for grader in graders if grader.get('type') != u'Entrance Exam']
|
||||
return graders
|
||||
|
||||
|
||||
@@ -352,18 +352,6 @@ FEATURES = {
|
||||
'ENABLE_CHANGE_USER_PASSWORD_ADMIN': False,
|
||||
|
||||
### ORA Feature Flags ###
|
||||
|
||||
# .. toggle_name: ENABLE_ORA_TEAM_SUBMISSIONS
|
||||
# .. toggle_implementation: DjangoSetting
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Set to True to enable team-based ORA submissions.
|
||||
# .. toggle_use_cases: temporary
|
||||
# .. toggle_creation_date: 2020-03-03
|
||||
# .. toggle_target_removal_date: None
|
||||
# .. toggle_tickets: https://openedx.atlassian.net/browse/EDUCATOR-4951
|
||||
# .. toggle_warnings: This temporary feature toggle does not have a target removal date.
|
||||
'ENABLE_ORA_TEAM_SUBMISSIONS': False,
|
||||
|
||||
# .. toggle_name: ENABLE_ORA_ALL_FILE_URLS
|
||||
# .. toggle_implementation: DjangoSetting
|
||||
# .. toggle_default: False
|
||||
|
||||
@@ -18,6 +18,8 @@ from cms.djangoapps.contentstore.views.organization import OrganizationListView
|
||||
from openedx.core.apidocs import api_info
|
||||
from openedx.core.djangoapps.password_policy import compliance as password_policy_compliance
|
||||
from openedx.core.djangoapps.password_policy.forms import PasswordPolicyAwareAdminAuthForm
|
||||
from openedx.core import toggles as core_toggles
|
||||
|
||||
|
||||
django_autodiscover()
|
||||
admin.site.site_header = _('Studio Administration')
|
||||
@@ -220,7 +222,7 @@ urlpatterns.append(url(r'^admin/password_change/$', handler404))
|
||||
urlpatterns.append(url(r'^admin/', admin.site.urls))
|
||||
|
||||
# enable entrance exams
|
||||
if settings.FEATURES.get('ENTRANCE_EXAMS'):
|
||||
if core_toggles.ENTRANCE_EXAMS.is_enabled():
|
||||
urlpatterns.append(url(r'^course/{}/entrance_exam/?$'.format(settings.COURSE_KEY_PATTERN),
|
||||
contentstore_views.entrance_exam))
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ from openedx.core.djangoapps.xmodule_django.models import NoneToEmptyManager
|
||||
from openedx.core.djangolib.model_mixins import DeletableByUserValue
|
||||
from student.signals import ENROLL_STATUS_CHANGE, ENROLLMENT_TRACK_UPDATED, UNENROLL_DONE
|
||||
from track import contexts, segment
|
||||
from util.milestones_helpers import is_entrance_exams_enabled
|
||||
from openedx.core.toggles import ENTRANCE_EXAMS
|
||||
from util.model_utils import emit_field_changed_events, get_changed_fields_dict
|
||||
from util.query import use_read_replica_if_available
|
||||
|
||||
@@ -2659,7 +2659,7 @@ class EntranceExamConfiguration(models.Model):
|
||||
Return True if given user can skip entrance exam for given course otherwise False.
|
||||
"""
|
||||
can_skip = False
|
||||
if is_entrance_exams_enabled():
|
||||
if ENTRANCE_EXAMS.is_enabled():
|
||||
try:
|
||||
record = EntranceExamConfiguration.objects.get(user=user, course_id=course_key)
|
||||
can_skip = record.skip_entrance_exam
|
||||
|
||||
@@ -6,6 +6,7 @@ Utility library for working with the edx-milestones app
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from edx_toggles.toggles import SettingDictToggle
|
||||
from milestones import api as milestones_api
|
||||
from milestones.exceptions import InvalidMilestoneRelationshipTypeException, InvalidUserException
|
||||
from milestones.models import MilestoneRelationshipType
|
||||
@@ -17,12 +18,23 @@ from openedx.core.djangoapps.content.course_overviews.models import CourseOvervi
|
||||
from openedx.core.lib.cache_utils import get_cache
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
|
||||
NAMESPACE_CHOICES = {
|
||||
'ENTRANCE_EXAM': 'entrance_exams'
|
||||
}
|
||||
|
||||
REQUEST_CACHE_NAME = "milestones"
|
||||
|
||||
# .. toggle_name: FEATURES['ENABLE_MILESTONES_APP']
|
||||
# .. toggle_implementation: SettingDictToggle
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Enable the milestones application, which manages significant Course and/or Student events in
|
||||
# the Open edX platform. (see https://github.com/edx/edx-milestones)
|
||||
# .. toggle_use_cases: open_edx
|
||||
# .. toggle_creation_date: 2014-11-21
|
||||
# TODO this should be moved to edx/edx-milestones
|
||||
ENABLE_MILESTONES_APP = SettingDictToggle("FEATURES", "MILESTONES_APP", default=False, module_name=__name__)
|
||||
|
||||
|
||||
def get_namespace_choices():
|
||||
"""
|
||||
@@ -31,19 +43,11 @@ def get_namespace_choices():
|
||||
return NAMESPACE_CHOICES
|
||||
|
||||
|
||||
def is_entrance_exams_enabled():
|
||||
"""
|
||||
Checks to see if the Entrance Exams feature is enabled
|
||||
Use this operation instead of checking the feature flag all over the place
|
||||
"""
|
||||
return settings.FEATURES.get('ENTRANCE_EXAMS')
|
||||
|
||||
|
||||
def is_prerequisite_courses_enabled():
|
||||
"""
|
||||
Returns boolean indicating prerequisite courses enabled system wide or not.
|
||||
"""
|
||||
return settings.FEATURES.get('ENABLE_PREREQUISITE_COURSES') and settings.FEATURES.get('MILESTONES_APP')
|
||||
return settings.FEATURES.get('ENABLE_PREREQUISITE_COURSES') and ENABLE_MILESTONES_APP.is_enabled()
|
||||
|
||||
|
||||
def add_prerequisite_course(course_key, prerequisite_course_key):
|
||||
@@ -185,7 +189,7 @@ def fulfill_course_milestone(course_key, user):
|
||||
Marks the course specified by the given course_key as complete for the given user.
|
||||
If any other courses require this course as a prerequisite, their milestones will be appropriately updated.
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
try:
|
||||
course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship="fulfills")
|
||||
@@ -201,7 +205,7 @@ def remove_course_milestones(course_key, user, relationship):
|
||||
"""
|
||||
Remove all user milestones for the course specified by course_key.
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
course_milestones = milestones_api.get_course_milestones(course_key=course_key, relationship=relationship)
|
||||
for milestone in course_milestones:
|
||||
@@ -214,7 +218,7 @@ def get_required_content(course_key, user):
|
||||
and if those milestones can be fulfilled via completion of a particular course content module
|
||||
"""
|
||||
required_content = []
|
||||
if settings.FEATURES.get('MILESTONES_APP'):
|
||||
if ENABLE_MILESTONES_APP.is_enabled():
|
||||
course_run_id = six.text_type(course_key)
|
||||
|
||||
if user.is_authenticated:
|
||||
@@ -248,7 +252,7 @@ def milestones_achieved_by_user(user, namespace):
|
||||
"""
|
||||
It would fetch list of milestones completed by user
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
return milestones_api.get_user_milestones({'id': user.id}, namespace)
|
||||
|
||||
@@ -268,7 +272,7 @@ def seed_milestone_relationship_types():
|
||||
"""
|
||||
Helper method to pre-populate MRTs so the tests can run
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
MilestoneRelationshipType.objects.create(name='requires')
|
||||
MilestoneRelationshipType.objects.create(name='fulfills')
|
||||
@@ -296,7 +300,7 @@ def add_milestone(milestone_data):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
return milestones_api.add_milestone(milestone_data)
|
||||
|
||||
@@ -305,7 +309,7 @@ def get_milestones(namespace):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return []
|
||||
return milestones_api.get_milestones(namespace)
|
||||
|
||||
@@ -314,7 +318,7 @@ def get_milestone_relationship_types():
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return {}
|
||||
return milestones_api.get_milestone_relationship_types()
|
||||
|
||||
@@ -323,7 +327,7 @@ def add_course_milestone(course_id, relationship, milestone):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
return milestones_api.add_course_milestone(course_id, relationship, milestone)
|
||||
|
||||
@@ -332,7 +336,7 @@ def get_course_milestones(course_id):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return []
|
||||
return milestones_api.get_course_milestones(course_id)
|
||||
|
||||
@@ -341,7 +345,7 @@ def add_course_content_milestone(course_id, content_id, relationship, milestone)
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
return milestones_api.add_course_content_milestone(course_id, content_id, relationship, milestone)
|
||||
|
||||
@@ -355,7 +359,7 @@ def get_course_content_milestones(course_id, content_id=None, relationship='requ
|
||||
Returns all content blocks in a course if content_id is None, otherwise it just returns that
|
||||
specific content block.
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return []
|
||||
|
||||
if user_id is None:
|
||||
@@ -382,7 +386,7 @@ def remove_course_content_user_milestones(course_key, content_key, user, relatio
|
||||
"""
|
||||
Removes the specified User-Milestone link from the system for the specified course content module.
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return []
|
||||
|
||||
course_content_milestones = milestones_api.get_course_content_milestones(course_key, content_key, relationship)
|
||||
@@ -394,14 +398,14 @@ def remove_content_references(content_id):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
return milestones_api.remove_content_references(content_id)
|
||||
|
||||
|
||||
def any_unfulfilled_milestones(course_id, user_id):
|
||||
""" Returns a boolean if user has any unfulfilled milestones """
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return False
|
||||
|
||||
user_id = None if user_id is None else int(user_id)
|
||||
@@ -416,7 +420,7 @@ def get_course_milestones_fulfillment_paths(course_id, user_id):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
return milestones_api.get_course_milestones_fulfillment_paths(
|
||||
course_id,
|
||||
@@ -428,7 +432,7 @@ def add_user_milestone(user, milestone):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
return milestones_api.add_user_milestone(user, milestone)
|
||||
|
||||
@@ -437,7 +441,7 @@ def remove_user_milestone(user, milestone):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP'):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
return milestones_api.remove_user_milestone(user, milestone)
|
||||
|
||||
@@ -450,6 +454,6 @@ def get_service():
|
||||
Note: MilestonesService only has access to the functions
|
||||
explicitly requested in the MilestonesServices class
|
||||
"""
|
||||
if not settings.FEATURES.get('MILESTONES_APP', False):
|
||||
if not ENABLE_MILESTONES_APP.is_enabled():
|
||||
return None
|
||||
return MilestonesService()
|
||||
|
||||
@@ -7,7 +7,8 @@ from opaque_keys.edx.keys import UsageKey
|
||||
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from student.models import EntranceExamConfiguration
|
||||
from util.milestones_helpers import get_required_content, is_entrance_exams_enabled
|
||||
from util.milestones_helpers import get_required_content
|
||||
from openedx.core.toggles import ENTRANCE_EXAMS
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
|
||||
@@ -15,7 +16,7 @@ def course_has_entrance_exam(course):
|
||||
"""
|
||||
Checks to see if a course is properly configured for an entrance exam
|
||||
"""
|
||||
if not is_entrance_exams_enabled():
|
||||
if not ENTRANCE_EXAMS.is_enabled():
|
||||
return False
|
||||
entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', None)
|
||||
if not entrance_exam_enabled:
|
||||
|
||||
@@ -11,6 +11,7 @@ from opaque_keys.edx.keys import UsageKey
|
||||
from lms.djangoapps.courseware.entrance_exams import get_entrance_exam_content
|
||||
from openedx.core.lib.gating import api as gating_api
|
||||
from util import milestones_helpers
|
||||
from openedx.core.toggles import ENTRANCE_EXAMS
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -48,7 +49,7 @@ def evaluate_entrance_exam(course_grade, user):
|
||||
fulfilled for the user.
|
||||
"""
|
||||
course = course_grade.course_data.course
|
||||
if milestones_helpers.is_entrance_exams_enabled() and getattr(course, 'entrance_exam_enabled', False):
|
||||
if ENTRANCE_EXAMS.is_enabled() and getattr(course, 'entrance_exam_enabled', False):
|
||||
if get_entrance_exam_content(user, course):
|
||||
exam_chapter_key = get_entrance_exam_usage_key(course)
|
||||
exam_score_ratio = get_entrance_exam_score_ratio(course_grade, exam_chapter_key)
|
||||
|
||||
43
lms/djangoapps/teams/toggles.py
Normal file
43
lms/djangoapps/teams/toggles.py
Normal file
@@ -0,0 +1,43 @@
|
||||
"""
|
||||
Togglable settings for Teams behavior
|
||||
"""
|
||||
from edx_toggles.toggles import SettingDictToggle
|
||||
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag
|
||||
|
||||
|
||||
# Course Waffle inherited from edx/edx-ora2
|
||||
WAFFLE_NAMESPACE = "openresponseassessment"
|
||||
TEAM_SUBMISSIONS_FLAG = "team_submissions"
|
||||
|
||||
# .. toggle_name: FEATURES['ENABLE_ORA_TEAM_SUBMISSIONS']
|
||||
# .. toggle_implementation: SettingDictToggle
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Set to True to enable team-based ORA submissions.
|
||||
# .. toggle_use_cases: temporary
|
||||
# .. toggle_creation_date: 2020-03-03
|
||||
# .. toggle_target_removal_date: None
|
||||
# .. toggle_tickets: https://openedx.atlassian.net/browse/EDUCATOR-4951
|
||||
# .. toggle_warnings: This temporary feature toggle does not have a target removal date. This can be overridden by a
|
||||
# course waffle flags or a waffle switch with identical name.
|
||||
# TODO: this should be moved to edx/edx-ora2
|
||||
TEAM_SUBMISSIONS_FEATURE = SettingDictToggle(
|
||||
"FEATURES", "ENABLE_ORA_TEAM_SUBMISSIONS", default=False, module_name=__name__
|
||||
)
|
||||
|
||||
|
||||
def are_team_submissions_enabled(course_key):
|
||||
"""
|
||||
Checks to see if the CourseWaffleFlag or Django setting for team submissions is enabled
|
||||
"""
|
||||
if CourseWaffleFlag(WAFFLE_NAMESPACE, TEAM_SUBMISSIONS_FLAG, __name__).is_enabled(
|
||||
course_key
|
||||
):
|
||||
return True
|
||||
|
||||
# TODO: this behaviour differs from edx-ora2, where the WaffleSwitch overrides the setting.
|
||||
# https://github.com/edx/edx-ora2/blob/ac502d8301cb987c9885aaefbaeddaf456c13fb9/openassessment/xblock/config_mixin.py#L96
|
||||
|
||||
if TEAM_SUBMISSIONS_FEATURE.is_enabled():
|
||||
return True
|
||||
|
||||
return False
|
||||
@@ -69,7 +69,7 @@ from .serializers import (
|
||||
TopicSerializer
|
||||
)
|
||||
from .utils import emit_team_event
|
||||
from .waffle import are_team_submissions_enabled
|
||||
from .toggles import are_team_submissions_enabled
|
||||
|
||||
TEAM_MEMBERSHIPS_PER_PAGE = 5
|
||||
TOPICS_PER_PAGE = 12
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
"""
|
||||
Togglable settings for Teams behavior
|
||||
"""
|
||||
from django.conf import settings
|
||||
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag
|
||||
|
||||
|
||||
# Course Waffle inherited from edx/edx-ora2
|
||||
WAFFLE_NAMESPACE = 'openresponseassessment'
|
||||
TEAM_SUBMISSIONS_FLAG = 'team_submissions'
|
||||
|
||||
# edx/edx-platform feature
|
||||
TEAM_SUBMISSIONS_FEATURE = 'ENABLE_ORA_TEAM_SUBMISSIONS'
|
||||
|
||||
|
||||
def are_team_submissions_enabled(course_key):
|
||||
"""
|
||||
Checks to see if the CourseWaffleFlag or Django setting for team submissions is enabled
|
||||
"""
|
||||
if CourseWaffleFlag(WAFFLE_NAMESPACE, TEAM_SUBMISSIONS_FLAG, __name__).is_enabled(course_key):
|
||||
return True
|
||||
|
||||
if settings.FEATURES.get(TEAM_SUBMISSIONS_FEATURE, False):
|
||||
return True
|
||||
|
||||
return False
|
||||
@@ -606,18 +606,6 @@ FEATURES = {
|
||||
'ENABLE_LOGISTRATION_MICROFRONTEND': False,
|
||||
|
||||
### ORA Feature Flags ###
|
||||
|
||||
# .. toggle_name: ENABLE_ORA_TEAM_SUBMISSIONS
|
||||
# .. toggle_implementation: DjangoSetting
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Set to True to enable team-based ORA submissions.
|
||||
# .. toggle_use_cases: temporary
|
||||
# .. toggle_creation_date: 2020-03-03
|
||||
# .. toggle_target_removal_date: None
|
||||
# .. toggle_tickets: https://openedx.atlassian.net/browse/EDUCATOR-4951
|
||||
# .. toggle_warnings: This temporary feature toggle does not have a target removal date.
|
||||
'ENABLE_ORA_TEAM_SUBMISSIONS': False,
|
||||
|
||||
# .. toggle_name: ENABLE_ORA_ALL_FILE_URLS
|
||||
# .. toggle_implementation: DjangoSetting
|
||||
# .. toggle_default: False
|
||||
|
||||
17
openedx/core/toggles.py
Normal file
17
openedx/core/toggles.py
Normal file
@@ -0,0 +1,17 @@
|
||||
"""
|
||||
Feature toggles used across the platform. Toggles should only be added to this module if we don't have a better place
|
||||
for them. Generally speaking, they should be added to the most appropriate app or repo.
|
||||
"""
|
||||
from edx_toggles.toggles import SettingDictToggle
|
||||
|
||||
# .. toggle_name: FEATURES['ENTRANCE_EXAMS']
|
||||
# .. toggle_implementation: SettingDictToggle
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Enable entrance exams feature. When enabled, students see an exam xblock as the first unit
|
||||
# of the course.
|
||||
# .. toggle_use_cases: open_edx
|
||||
# .. toggle_creation_date: 2015-12-01
|
||||
# .. toggle_tickets: https://openedx.atlassian.net/browse/SOL-40
|
||||
ENTRANCE_EXAMS = SettingDictToggle(
|
||||
"FEATURES", "ENTRANCE_EXAMS", default=False, module_name=__name__
|
||||
)
|
||||
@@ -2,4 +2,5 @@ from sys_path_hacks.warn import warn_deprecated_import
|
||||
|
||||
warn_deprecated_import('lms.djangoapps', 'teams.waffle')
|
||||
|
||||
from lms.djangoapps.teams.waffle import *
|
||||
# pylint: disable=wildcard-import
|
||||
from lms.djangoapps.teams.toggles import *
|
||||
|
||||
Reference in New Issue
Block a user