diff --git a/Dockerfile b/Dockerfile
index 94bea46e56..6948fefcf8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -119,7 +119,7 @@ RUN nodeenv /edx/app/edxapp/nodeenv --node=16.14.0 --prebuilt
RUN npm install -g npm@8.5.x
COPY package.json package.json
COPY package-lock.json package-lock.json
-RUN npm set progress=false && npm install
+RUN npm set progress=false && npm ci
# The builder-development stage is a temporary stage that installs python modules required for development purposes
# The built artifacts from this stage are then copied to the development stage.
diff --git a/cms/templates/widgets/header.html b/cms/templates/widgets/header.html
index 39efc419ff..57e40c35ff 100644
--- a/cms/templates/widgets/header.html
+++ b/cms/templates/widgets/header.html
@@ -125,9 +125,16 @@
${_("Pages & Resources")}
% endif
+ %if not files_uploads_mfe_enabled:
${_("Files & Uploads")}
+ %endif
+ %if files_uploads_mfe_enabled:
+
+ ${_("Files & Media")}
+
+ %endif
% if not pages_and_resources_mfe_enabled:
${_("Textbooks")}
@@ -199,7 +206,7 @@
% endif
% if has_studio_advanced_settings_access(request.user) and advanced_settings_mfe_enabled:
- ${_("Advanced Settings")}
+ ${_("Advanced Settings")}
% endif
% if certificates_url:
@@ -222,12 +229,26 @@
+ % if not import_mfe_enabled:
-
${_("Import")}
+ % endif
+ % if import_mfe_enabled:
+ -
+ ${_("Import")}
+
+ % endif
+ % if not export_mfe_enabled:
-
${_("Export")}
+ % endif
+ % if export_mfe_enabled:
+ -
+ ${_("Import")}
+
+ % endif
% if toggles.EXPORT_GIT.is_enabled() and context_course.giturl:
-
${_("Export to Git")}
diff --git a/common/static/data/geoip/GeoLite2-Country.mmdb b/common/static/data/geoip/GeoLite2-Country.mmdb
index 4459e8a8b2..13ec528cd5 100644
Binary files a/common/static/data/geoip/GeoLite2-Country.mmdb and b/common/static/data/geoip/GeoLite2-Country.mmdb differ
diff --git a/lms/djangoapps/learner_recommendations/serializers.py b/lms/djangoapps/learner_recommendations/serializers.py
index 75328e9d06..24e0a4ddd1 100644
--- a/lms/djangoapps/learner_recommendations/serializers.py
+++ b/lms/djangoapps/learner_recommendations/serializers.py
@@ -60,16 +60,18 @@ class AboutPageProductRecommendationsSerializer(serializers.Serializer):
class LearnerDashboardProductRecommendationsSerializer(serializers.Serializer):
"""Serializer for product recommendations for the Learner Dashboard"""
title = serializers.CharField()
+ courseRunKey = serializers.SerializerMethodField()
+ marketingUrl = serializers.URLField(source="marketing_url")
+ courseType = serializers.CharField(source="course_type")
image = CourseImageSerializer()
- prospectusPath = serializers.SerializerMethodField()
owners = serializers.ListField(
child=CourseOwnersSerializer(), allow_empty=True
)
- courseType = serializers.CharField(source="course_type")
- def get_prospectusPath(self, instance):
- url_slug = instance.get("url_slug")
- return f"course/{url_slug}"
+ def get_courseRunKey(self, instance):
+ active_course_run_key = instance.get('active_course_run_key')
+
+ return active_course_run_key if active_course_run_key else instance.get('course_runs')[0]['key']
class AboutPageRecommendationsSerializer(serializers.Serializer):
diff --git a/lms/djangoapps/learner_recommendations/tests/test_data.py b/lms/djangoapps/learner_recommendations/tests/test_data.py
index 2bd4d7350a..2ecbb5de59 100644
--- a/lms/djangoapps/learner_recommendations/tests/test_data.py
+++ b/lms/djangoapps/learner_recommendations/tests/test_data.py
@@ -48,10 +48,12 @@ mock_course_data = [
mock_cross_product_data = [
{
"title": "Title 0",
+ "courseRunKey": "course-v1:Test+2023_T0",
+ "marketingUrl": "https://www.marketing_url0.com",
+ "courseType": "executive-education",
"image": {
"src": "https://www.logo_image_url0.com"
},
- "prospectusPath": "course/https://www.marketing_url0.com",
"owners": [
{
"key": "org-0",
@@ -59,14 +61,15 @@ mock_cross_product_data = [
"logoImageUrl": "https://discovery.com/organization/logos/org-0.png"
}
],
- "courseType": "executive-education"
},
{
"title": "Title 1",
+ "courseRunKey": "course-v1:Test+2023_T1",
+ "marketingUrl": "https://www.marketing_url1.com",
+ "courseType": "executive-education",
"image": {
"src": "https://www.logo_image_url1.com"
},
- "prospectusPath": "course/https://www.marketing_url1.com",
"owners": [
{
"key": "org-1",
@@ -74,7 +77,6 @@ mock_cross_product_data = [
"logoImageUrl": "https://discovery.com/organization/logos/org-1.png"
}
],
- "courseType": "executive-education"
},
]
@@ -82,10 +84,12 @@ mock_amplitude_data = [
*mock_cross_product_data,
{
"title": "Title 2",
+ "courseRunKey": "course-v1:Test+2023_T2",
+ "marketingUrl": "https://www.marketing_url2.com",
+ "courseType": "executive-education",
"image": {
"src": "https://www.logo_image_url2.com"
},
- "prospectusPath": "course/https://www.marketing_url2.com",
"owners": [
{
"key": "org-2",
@@ -93,14 +97,15 @@ mock_amplitude_data = [
"logoImageUrl": "https://discovery.com/organization/logos/org-2.png"
}
],
- "courseType": "executive-education"
},
{
"title": "Title 3",
+ "courseRunKey": "course-v1:Test+2023_T3",
+ "marketingUrl": "https://www.marketing_url3.com",
+ "courseType": "executive-education",
"image": {
"src": "https://www.logo_image_url3.com"
},
- "prospectusPath": "course/https://www.marketing_url3.com",
"owners": [
{
"key": "org-3",
@@ -108,7 +113,6 @@ mock_amplitude_data = [
"logoImageUrl": "https://discovery.com/organization/logos/org-3.png"
}
],
- "courseType": "executive-education"
}
]
@@ -125,6 +129,11 @@ def get_general_recommendations():
"course_type": "credit-verified-audit",
"logo_image_url": "https://discovery.com/organization/logos/org-1.png",
"marketing_url": "https://www.marketing_url.com",
+ "course_runs": [
+ {
+ "key": "course-v1:MITx+6.00.1x+2T2023",
+ }
+ ],
"owners": [
{
"key": "MITx",
diff --git a/lms/djangoapps/learner_recommendations/tests/test_serializers.py b/lms/djangoapps/learner_recommendations/tests/test_serializers.py
index 17cb9f1523..47b0ae8037 100644
--- a/lms/djangoapps/learner_recommendations/tests/test_serializers.py
+++ b/lms/djangoapps/learner_recommendations/tests/test_serializers.py
@@ -97,7 +97,7 @@ class TestCrossProductRecommendationsSerializers(TestCase):
AmplitudeRecommendationsSerializer, and CrossProductAndAmplitudeRecommendations Serializer
"""
- def mock_recommended_courses(self, num_of_courses=2, amplitude_courses=False):
+ def mock_recommended_courses(self, num_of_courses=2):
"""Course data mock"""
recommended_courses = []
@@ -132,20 +132,12 @@ class TestCrossProductRecommendationsSerializers(TestCase):
"marketing_url": f"https://www.marketing_url{index}.com",
"availability": "Current",
},
+ "active_course_run_key": f"course-v1:Test+2023_T{index}",
+ "marketing_url": f"https://www.marketing_url{index}.com",
"location_restriction": None
},
)
- if amplitude_courses:
- keys_to_remove = ["active_course_run", "key", "uuid"]
- amplitude_courses = []
-
- for course in recommended_courses:
- new_course = {key: value for key, value in course.items() if key not in keys_to_remove}
- amplitude_courses.append(new_course)
-
- return amplitude_courses
-
return recommended_courses
def test_successful_cross_product_recommendation_serialization(self):
@@ -178,7 +170,7 @@ class TestCrossProductRecommendationsSerializers(TestCase):
"""Test that course data serializes correctly for CrossProductAndAmplitudeRecommendationSerializer"""
cross_product_courses = self.mock_recommended_courses(num_of_courses=2)
- amplitude_courses = self.mock_recommended_courses(num_of_courses=4, amplitude_courses=True)
+ amplitude_courses = self.mock_recommended_courses(num_of_courses=4)
serialized_data = CrossProductAndAmplitudeRecommendationsSerializer({
"crossProductCourses": cross_product_courses,
diff --git a/lms/djangoapps/learner_recommendations/tests/test_views.py b/lms/djangoapps/learner_recommendations/tests/test_views.py
index b95264f2a3..8d5edd1602 100644
--- a/lms/djangoapps/learner_recommendations/tests/test_views.py
+++ b/lms/djangoapps/learner_recommendations/tests/test_views.py
@@ -387,13 +387,12 @@ class TestProductRecommendationsView(APITestCase):
"image": {
"src": "https://www.logo_image_url.com",
},
- "url_slug": "https://www.marketing_url.com",
"course_type": "executive-education",
"owners": [
{
- "key": "org-1",
- "name": "org 1",
- "logo_image_url": "https://discovery.com/organization/logos/org-1.png",
+ "key": "org-1",
+ "name": "org 1",
+ "logo_image_url": "https://discovery.com/organization/logos/org-1.png",
},
],
"course_runs": [
@@ -405,6 +404,8 @@ class TestProductRecommendationsView(APITestCase):
"status": "published"
}
],
+ "marketing_url": "https://www.marketing_url.com/course/some-course",
+ "advertised_course_run_uuid": f"course-v1:{key}+2023_T2",
}
if keys_with_restriction and key in keys_with_restriction:
course.update({
diff --git a/lms/djangoapps/learner_recommendations/views.py b/lms/djangoapps/learner_recommendations/views.py
index a673b8f5c0..ed465bdf8e 100644
--- a/lms/djangoapps/learner_recommendations/views.py
+++ b/lms/djangoapps/learner_recommendations/views.py
@@ -213,10 +213,11 @@ class ProductRecommendationsView(APIView):
"title",
"owners",
"image",
- "url_slug",
"course_type",
"course_runs",
"location_restriction",
+ "marketing_url",
+ "advertised_course_run_uuid",
]
def _get_amplitude_recommendations(self, user, user_country_code):
@@ -262,6 +263,9 @@ class ProductRecommendationsView(APIView):
and course.get("course_runs", [])
and not _has_country_restrictions(course, user_country_code)
):
+ active_course_run = get_active_course_run(course)
+ if active_course_run:
+ course.update({"active_course_run_key": active_course_run.get("key")})
filtered_cross_product_courses.append(course)
diff --git a/openedx/core/djangoapps/content/block_structure/config/__init__.py b/openedx/core/djangoapps/content/block_structure/config/__init__.py
index 9bac61bf9b..df82bfb068 100644
--- a/openedx/core/djangoapps/content/block_structure/config/__init__.py
+++ b/openedx/core/djangoapps/content/block_structure/config/__init__.py
@@ -10,23 +10,6 @@ from openedx.core.lib.cache_utils import request_cached
from .models import BlockStructureConfiguration
# Switches
-# .. toggle_name: block_structure.invalidate_cache_on_publish
-# .. toggle_implementation: WaffleSwitch
-# .. toggle_default: False
-# .. toggle_description: When enabled, the block structure cache is invalidated when changes to
-# courses are published. If `block_structure.storage_backing_for_cache` is active, all block
-# structures related to the published course are also cleared from storage.
-# .. toggle_warning: This switch will likely be deprecated and removed.
-# .. toggle_use_cases: temporary
-# .. toggle_creation_date: 2017-02-23
-# .. toggle_target_removal_date: 2017-05-23
-# .. toggle_tickets: https://github.com/openedx/edx-platform/pull/14358,
-# https://github.com/openedx/edx-platform/pull/14571,
-# https://openedx.atlassian.net/browse/DEPR-144
-INVALIDATE_CACHE_ON_PUBLISH = WaffleSwitch(
- "block_structure.invalidate_cache_on_publish", __name__
-)
-
# .. toggle_name: block_structure.storage_backing_for_cache
# .. toggle_implementation: WaffleSwitch
# .. toggle_default: False
diff --git a/openedx/core/djangoapps/content/block_structure/signals.py b/openedx/core/djangoapps/content/block_structure/signals.py
index d3cae5f2c0..d097216d26 100644
--- a/openedx/core/djangoapps/content/block_structure/signals.py
+++ b/openedx/core/djangoapps/content/block_structure/signals.py
@@ -10,9 +10,7 @@ from opaque_keys.edx.locator import LibraryLocator
from xmodule.modulestore.django import SignalHandler
-from . import config
from .api import clear_course_from_cache
-from .models import BlockStructureNotFound
from .tasks import update_course_in_cache_v2
log = logging.getLogger(__name__)
@@ -28,15 +26,6 @@ def update_block_structure_on_course_publish(sender, course_key, **kwargs): # p
if isinstance(course_key, LibraryLocator):
return
- if config.INVALIDATE_CACHE_ON_PUBLISH.is_enabled():
- try:
- clear_course_from_cache(course_key)
- except BlockStructureNotFound:
- log.warning(
- "BlockStructure: %s not found when trying to clear course from cache",
- course_key,
- )
-
update_course_in_cache_v2.apply_async(
kwargs=dict(course_id=str(course_key)),
countdown=settings.BLOCK_STRUCTURES_SETTINGS['COURSE_PUBLISH_TASK_DELAY'],
diff --git a/openedx/core/djangoapps/content/block_structure/tests/test_signals.py b/openedx/core/djangoapps/content/block_structure/tests/test_signals.py
index 920b663cb8..af35873125 100644
--- a/openedx/core/djangoapps/content/block_structure/tests/test_signals.py
+++ b/openedx/core/djangoapps/content/block_structure/tests/test_signals.py
@@ -5,14 +5,12 @@ from unittest.mock import patch
import pytest
import ddt
-from edx_toggles.toggles.testutils import override_waffle_switch
from opaque_keys.edx.locator import CourseLocator, LibraryLocator
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from ..api import get_block_structure_manager
-from ..config import INVALIDATE_CACHE_ON_PUBLISH
from ..signals import update_block_structure_on_course_publish
from .helpers import is_course_in_block_structure_cache
@@ -45,17 +43,6 @@ class CourseBlocksSignalTest(ModuleStoreTestCase):
updated_block_structure = bs_manager.get_collected()
assert test_display_name == updated_block_structure.get_xblock_field(self.course_usage_key, 'display_name')
- @ddt.data(True, False)
- @patch('openedx.core.djangoapps.content.block_structure.manager.BlockStructureManager.clear')
- def test_cache_invalidation(self, invalidate_cache_enabled, mock_bs_manager_clear):
- test_display_name = "Jedi 101"
-
- with override_waffle_switch(INVALIDATE_CACHE_ON_PUBLISH, active=invalidate_cache_enabled):
- self.course.display_name = test_display_name
- self.update_course(self.course, self.user.id)
-
- assert mock_bs_manager_clear.called == invalidate_cache_enabled
-
def test_course_delete(self):
bs_manager = get_block_structure_manager(self.course.id)
assert bs_manager.get_collected() is not None
diff --git a/openedx/core/djangoapps/content/course_overviews/migrations/0028_flex_peer_ora_course_setting.py b/openedx/core/djangoapps/content/course_overviews/migrations/0028_flex_peer_ora_course_setting.py
new file mode 100644
index 0000000000..5a5ad9b2b6
--- /dev/null
+++ b/openedx/core/djangoapps/content/course_overviews/migrations/0028_flex_peer_ora_course_setting.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.2.19 on 2023-06-28 13:35
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('course_overviews', '0027_auto_20221102_1109'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='courseoverview',
+ name='force_on_flexible_peer_openassessments',
+ field=models.BooleanField(default=False),
+ ),
+ migrations.AddField(
+ model_name='historicalcourseoverview',
+ name='force_on_flexible_peer_openassessments',
+ field=models.BooleanField(default=False),
+ ),
+ ]
diff --git a/openedx/core/djangoapps/content/course_overviews/models.py b/openedx/core/djangoapps/content/course_overviews/models.py
index 3c7290a755..d3101b6054 100644
--- a/openedx/core/djangoapps/content/course_overviews/models.py
+++ b/openedx/core/djangoapps/content/course_overviews/models.py
@@ -64,7 +64,7 @@ class CourseOverview(TimeStampedModel):
app_label = 'course_overviews'
# IMPORTANT: Bump this whenever you modify this model and/or add a migration.
- VERSION = 18
+ VERSION = 19
# Cache entry versioning.
version = models.IntegerField()
@@ -144,6 +144,9 @@ class CourseOverview(TimeStampedModel):
entrance_exam_id = models.CharField(max_length=255, blank=True)
entrance_exam_minimum_score_pct = models.FloatField(default=0.65)
+ # Open Response Assessment configuration
+ force_on_flexible_peer_openassessments = models.BooleanField(default=False)
+
external_id = models.CharField(max_length=128, null=True, blank=True)
language = models.TextField(null=True)
@@ -268,6 +271,8 @@ class CourseOverview(TimeStampedModel):
else:
course_overview.entrance_exam_minimum_score_pct = course.entrance_exam_minimum_score_pct
+ course_overview.force_on_flexible_peer_openassessments = course.force_on_flexible_peer_openassessments
+
if not CatalogIntegration.is_enabled():
course_overview.language = course.language
diff --git a/pavelib/paver_tests/test_prereqs.py b/pavelib/paver_tests/test_prereqs.py
index 2d4bdd6ab9..4b542ae97b 100644
--- a/pavelib/paver_tests/test_prereqs.py
+++ b/pavelib/paver_tests/test_prereqs.py
@@ -87,7 +87,7 @@ class TestPaverNodeInstall(PaverTestCase):
def test_npm_install_with_subprocess_error(self):
"""
- Test an error in 'npm install' execution
+ Test an error in 'npm ci' execution
"""
with patch('subprocess.Popen') as _mock_popen:
_mock_subprocess = mock.Mock()
@@ -97,21 +97,21 @@ class TestPaverNodeInstall(PaverTestCase):
with pytest.raises(Exception):
pavelib.prereqs.node_prereqs_installation()
- # npm install will be called twice
+ # npm ci will be called twice
assert _mock_popen.call_count == 2
def test_npm_install_called_once_when_successful(self):
"""
- Vanilla npm install should only be calling npm install one time
+ Vanilla npm ci should only be calling npm ci one time
"""
with patch('subprocess.Popen') as _mock_popen:
pavelib.prereqs.node_prereqs_installation()
- # when there's no failure, npm install is only called once
+ # when there's no failure, npm ci is only called once
assert _mock_popen.call_count == 1
def test_npm_install_with_unexpected_subprocess_error(self):
"""
- If there's some other error, only call npm install once, and raise a failure
+ If there's some other error, only call npm ci once, and raise a failure
"""
with patch('subprocess.Popen') as _mock_popen:
_mock_popen.side_effect = unexpected_fail_on_npm_install
diff --git a/pavelib/prereqs.py b/pavelib/prereqs.py
index 33cbab7ef9..ebb49aeacb 100644
--- a/pavelib/prereqs.py
+++ b/pavelib/prereqs.py
@@ -137,7 +137,7 @@ def node_prereqs_installation():
else:
npm_log_file_path = f'{Env.GEN_LOG_DIR}/npm-install.log'
npm_log_file = open(npm_log_file_path, 'wb') # lint-amnesty, pylint: disable=consider-using-with
- npm_command = 'npm clean-install --verbose'.split()
+ npm_command = 'npm ci --verbose'.split()
# The implementation of Paver's `sh` function returns before the forked
# actually returns. Using a Popen object so that we can ensure that
@@ -145,14 +145,7 @@ def node_prereqs_installation():
proc = subprocess.Popen(npm_command, stderr=npm_log_file) # lint-amnesty, pylint: disable=consider-using-with
retcode = proc.wait()
if retcode == 1:
- # Error handling around a race condition that produces "cb() never called" error. This
- # evinces itself as `cb_error_text` and it ought to disappear when we upgrade
- # npm to 3 or higher. TODO: clean this up when we do that.
- print("npm clean-install error detected. Retrying...")
- proc = subprocess.Popen(npm_command, stderr=npm_log_file) # lint-amnesty, pylint: disable=consider-using-with
- retcode = proc.wait()
- if retcode == 1:
- raise Exception(f"npm install failed: See {npm_log_file_path}")
+ raise Exception(f"npm install failed: See {npm_log_file_path}")
print("Successfully clean-installed NPM packages. Log found at {}".format(
npm_log_file_path
))
diff --git a/requirements/constraints.txt b/requirements/constraints.txt
index fe6a75549b..ee8a214c5a 100644
--- a/requirements/constraints.txt
+++ b/requirements/constraints.txt
@@ -32,7 +32,7 @@ django-storages==1.9.1
# The team that owns this package will manually bump this package rather than having it pulled in automatically.
# This is to allow them to better control its deployment and to do it in a process that works better
# for them.
-edx-enterprise==3.67.5
+edx-enterprise==3.67.7
# oauthlib>3.0.1 causes test failures ( also remove the django-oauth-toolkit constraint when this is fixed )
oauthlib==3.0.1
diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt
index fab054c72b..a0a2634e2c 100644
--- a/requirements/edx/base.txt
+++ b/requirements/edx/base.txt
@@ -489,7 +489,7 @@ edx-drf-extensions==8.8.0
# edx-when
# edxval
# learner-pathway-progress
-edx-enterprise==3.67.5
+edx-enterprise==3.67.7
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.in
diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt
index 9e9d831849..8f1af5a5e5 100644
--- a/requirements/edx/development.txt
+++ b/requirements/edx/development.txt
@@ -617,7 +617,7 @@ edx-drf-extensions==8.8.0
# edx-when
# edxval
# learner-pathway-progress
-edx-enterprise==3.67.5
+edx-enterprise==3.67.7
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/testing.txt
diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt
index f47779ba2a..714d0878c0 100644
--- a/requirements/edx/testing.txt
+++ b/requirements/edx/testing.txt
@@ -590,7 +590,7 @@ edx-drf-extensions==8.8.0
# edx-when
# edxval
# learner-pathway-progress
-edx-enterprise==3.67.5
+edx-enterprise==3.67.7
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
diff --git a/setup.cfg b/setup.cfg
index 0be99c9402..d6328b4af8 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -115,6 +115,11 @@ ignore_imports =
# cms.djangoapps.export_course_metadata.tasks
# -> openedx.core.djangoapps.schedules.content_highlights
# -> lms.djangoapps.courseware.block_render & lms.djangoapps.courseware.model_data
+ openedx.core.djangoapps.content_libraries.* -> lms.djangoapps.grades.api
+ # cms.djangoapps.contentstore.tasks -> openedx.core.djangoapps.content_libraries.models
+ # -> openedx.core.djangoapps.content_libraries.apps
+ # -> openedx.core.djangoapps.content_libraries.signal_handlers
+ # -> lms.djangoapps.grades.api
openedx.core.djangoapps.schedules.content_highlights -> lms.djangoapps.courseware.*
# cms.djangoapps.contentstore.[various]
# -> openedx.core.lib.gating.api
diff --git a/xmodule/course_block.py b/xmodule/course_block.py
index f1847e2d9a..6ef625086b 100644
--- a/xmodule/course_block.py
+++ b/xmodule/course_block.py
@@ -978,6 +978,13 @@ class CourseFields: # lint-amnesty, pylint: disable=missing-class-docstring
]
)
+ force_on_flexible_peer_openassessments = Boolean(
+ display_name=_("Force Flexible Grading for Peer ORAs"),
+ help=_("Setting this flag will force on the flexible grading option for all peer-graded ORAs in this course."),
+ scope=Scope.settings,
+ default=False,
+ )
+
"""
instructor_info dict structure:
{
diff --git a/xmodule/static/sass/include/capa/display.scss b/xmodule/static/sass/include/capa/display.scss
index 990ba28b2a..15571b65dc 100644
--- a/xmodule/static/sass/include/capa/display.scss
+++ b/xmodule/static/sass/include/capa/display.scss
@@ -879,7 +879,7 @@ div.problem {
// ====================
.problem {
.inputtype.option-input {
- margin: (-$baseline/2) 0 $baseline;
+ margin: 0 0 0 0 !important;
.indicator-container {
display: inline-block;