Skip to content

Commit

Permalink
Merge branch 'master' into get_issued_certificates-to-drf
Browse files Browse the repository at this point in the history
  • Loading branch information
awais786 authored Nov 25, 2024
2 parents f460463 + 73ba58a commit b80ed2f
Show file tree
Hide file tree
Showing 104 changed files with 7,427 additions and 7,239 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/verify-dunder-init.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: CI
name: Verify Dunder __init__.py Files

on:
pull_request:
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: 2
build:
os: "ubuntu-22.04"
tools:
python: "3.12"
python: "3.11"

sphinx:
configuration: docs/conf.py
Expand Down
13 changes: 11 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ System Dependencies
-------------------

OS:
* Ubuntu 20.04

* Ubuntu 22.04

* Ubuntu 24.04

Interperters/Tools:

* Python 3.11
Expand Down Expand Up @@ -107,6 +107,15 @@ Language Packages:

Some Python packages have system dependencies. For example, installing these packages on Debian or Ubuntu will require first running ``sudo apt install python3-dev default-libmysqlclient-dev build-essential pkg-config`` to satisfy the requirements of the ``mysqlclient`` Python package.

Codejail Setup
--------------

As a part of the baremetal setup, you will need to configure your system to
work properly with codejail. See the `codejail installation steps`_ for more
details.

.. _codejail installation steps: https://github.com/openedx/codejail?tab=readme-ov-file#installation

Build Steps
-----------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class CourseWaffleFlagsSerializer(serializers.Serializer):
use_new_certificates_page = serializers.SerializerMethodField()
use_new_textbooks_page = serializers.SerializerMethodField()
use_new_group_configurations_page = serializers.SerializerMethodField()
enable_course_optimizer = serializers.SerializerMethodField()

def get_course_key(self):
"""
Expand Down Expand Up @@ -144,3 +145,10 @@ def get_use_new_group_configurations_page(self, obj):
"""
course_key = self.get_course_key()
return toggles.use_new_group_configurations_page(course_key)

def get_enable_course_optimizer(self, obj):
"""
Method to get the enable_course_optimizer waffle flag
"""
course_key = self.get_course_key()
return toggles.enable_course_optimizer(course_key)
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class CourseWaffleFlagsViewTest(CourseTestCase):
"use_new_group_configurations_page",
]

other_expected_waffle_flags = ["enable_course_optimizer"]

def setUp(self):
"""
Set up test data and state before each test method.
Expand All @@ -46,6 +48,18 @@ def setUp(self):
super().setUp()
self.url = reverse("cms.djangoapps.contentstore:v1:course_waffle_flags")
self.create_waffle_flags(self.course_waffle_flags)
self.create_custom_waffle_flags()

def create_custom_waffle_flags(self, enabled=True):
"""
Helper method to create waffle flags that are not part of `course_waffle_flags` and have
a different format.
"""
WaffleFlagCourseOverrideModel.objects.create(
waffle_flag="contentstore.enable_course_optimizer",
course_id=self.course.id,
enabled=enabled,
)

def create_waffle_flags(self, flags, enabled=True):
"""
Expand All @@ -72,7 +86,10 @@ def expected_response(self, enabled=False):
Returns:
dict: A dictionary with each flag set to the value of `enabled`.
"""
return {flag: enabled for flag in self.course_waffle_flags}
res = {flag: enabled for flag in self.course_waffle_flags}
for flag in self.other_expected_waffle_flags:
res[flag] = enabled
return res

def test_get_course_waffle_flags_with_course_id(self):
"""
Expand Down
20 changes: 20 additions & 0 deletions cms/djangoapps/contentstore/toggles.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,3 +667,23 @@ def libraries_v2_enabled():
search_api.is_meilisearch_enabled() and
not DISABLE_NEW_LIBRARIES.is_enabled()
)


# .. toggle_name: contentstore.enable_course_optimizer
# .. toggle_implementation: CourseWaffleFlag
# .. toggle_default: False
# .. toggle_description: This flag enables the use of unique anonymous_user_id during studio preview
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2022-05-04
# .. toggle_target_removal_date: 2022-05-30
# .. toggle_tickets: MST-1455
ENABLE_COURSE_OPTIMIZER = CourseWaffleFlag(
f'{CONTENTSTORE_NAMESPACE}.enable_course_optimizer', __name__
)


def enable_course_optimizer(course_id):
"""
Returns a boolean if individualized anonymous_user_id is enabled on the course
"""
return ENABLE_COURSE_OPTIMIZER.is_enabled(course_id)
19 changes: 11 additions & 8 deletions cms/djangoapps/contentstore/views/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,19 @@

# NOTE: This list is disjoint from ADVANCED_COMPONENT_TYPES
COMPONENT_TYPES = [
'discussion',
'library',
'library_v2', # Not an XBlock
'itembank',
'html',
'openassessment',
'problem',
'video',
'problem',
'itembank',
'library_v2', # Not an XBlock
'library',
'discussion',
'openassessment',
'drag-and-drop-v2',
]

BETA_COMPONENT_TYPES = ['library_v2', 'itembank']

ADVANCED_COMPONENT_TYPES = sorted({name for name, class_ in XBlock.load_classes()} - set(COMPONENT_TYPES))

ADVANCED_PROBLEM_TYPES = settings.ADVANCED_PROBLEM_TYPES
Expand Down Expand Up @@ -426,7 +428,8 @@ def create_support_legend_dict():
"type": category,
"templates": templates_for_category,
"display_name": component_display_names[category],
"support_legend": create_support_legend_dict()
"support_legend": create_support_legend_dict(),
"beta": category in BETA_COMPONENT_TYPES,
})

# Libraries do not support advanced components at this time.
Expand Down Expand Up @@ -476,7 +479,7 @@ def create_support_legend_dict():
course_advanced_keys
)
if advanced_component_templates['templates']:
component_templates.insert(0, advanced_component_templates)
component_templates.append(advanced_component_templates)

return component_templates

Expand Down
6 changes: 3 additions & 3 deletions cms/djangoapps/contentstore/views/tests/test_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -3184,13 +3184,13 @@ def _verify_advanced_xblocks(self, expected_xblocks, expected_support_levels):
templates = get_component_templates(self.course)
button_names = [template["display_name"] for template in templates]
self.assertIn("Advanced", button_names)
self.assertEqual(len(templates[0]["templates"]), len(expected_xblocks))
self.assertEqual(len(templates[-1]["templates"]), len(expected_xblocks))
template_display_names = [
template["display_name"] for template in templates[0]["templates"]
template["display_name"] for template in templates[-1]["templates"]
]
self.assertEqual(template_display_names, expected_xblocks)
template_support_levels = [
template["support_level"] for template in templates[0]["templates"]
template["support_level"] for template in templates[-1]["templates"]
]
self.assertEqual(template_support_levels, expected_support_levels)

Expand Down
4 changes: 3 additions & 1 deletion cms/static/js/models/component_template.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ define(['backbone'], function(Backbone) {
// boilerplate_name (may be null)
// is_common (only used for problems)
templates: [],
support_legend: {}
support_legend: {},
beta: false,
},
parse: function(response) {
// Returns true only for templates that both have no boilerplate and are of
Expand All @@ -26,6 +27,7 @@ define(['backbone'], function(Backbone) {
this.templates = response.templates;
this.display_name = response.display_name;
this.support_legend = response.support_legend;
this.beta = response.beta;

// Sort the templates.
this.templates.sort(function(a, b) {
Expand Down
3 changes: 2 additions & 1 deletion cms/static/js/views/components/add_xblock_button.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ define(['js/views/baseview', 'edx-ui-toolkit/js/utils/html-utils'],
var attributes = {
type: this.model.type,
templates: this.model.templates,
display_name: this.model.display_name
display_name: this.model.display_name,
beta: this.model.beta,
};
BaseView.prototype.initialize.call(this);
this.template = this.loadTemplate('add-xblock-component-button');
Expand Down
29 changes: 17 additions & 12 deletions cms/static/js/views/modals/preview_v2_library_changes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
* authors to preview the new version of a library-sourced XBlock, and decide
* whether to accept ("sync") or reject ("ignore") the changes.
*/
define(['jquery', 'underscore', 'gettext', 'js/views/modals/base_modal',
'common/js/components/utils/view_utils', 'js/views/utils/xblock_utils'],
function($, _, gettext, BaseModal, ViewUtils, XBlockViewUtils) {
define(['jquery', 'underscore', 'gettext', 'js/views/modals/base_modal', 'common/js/components/utils/view_utils'],
function($, _, gettext, BaseModal, ViewUtils) {
'use strict';

var PreviewLibraryChangesModal = BaseModal.extend({
Expand Down Expand Up @@ -40,18 +39,24 @@ function($, _, gettext, BaseModal, ViewUtils, XBlockViewUtils) {

/**
* Show an edit modal for the specified xblock
* @param xblockElement The element that contains the xblock to be edited.
* @param rootXBlockInfo An XBlockInfo model that describes the root xblock on the page.
* @param xblockInfo The XBlockInfo model that describes the xblock.
* @param courseAuthoringMfeUrl The course authoring mfe url.
* @param upstreamBlockId The library block id.
* @param upstreamBlockVersionSynced The library block current version.
* @param refreshFunction A function to refresh the block after it has been updated
*/
showPreviewFor: function(xblockElement, rootXBlockInfo, refreshFunction) {
this.xblockElement = xblockElement;
this.xblockInfo = XBlockViewUtils.findXBlockInfo(xblockElement, rootXBlockInfo);
this.courseAuthoringMfeUrl = rootXBlockInfo.attributes.course_authoring_url;
const headerElement = xblockElement.find('.xblock-header-primary');
showPreviewFor: function(
xblockInfo,
courseAuthoringMfeUrl,
upstreamBlockId,
upstreamBlockVersionSynced,
refreshFunction
) {
this.xblockInfo = xblockInfo;
this.courseAuthoringMfeUrl = courseAuthoringMfeUrl;
this.downstreamBlockId = this.xblockInfo.get('id');
this.upstreamBlockId = headerElement.data('upstream-ref');
this.upstreamBlockVersionSynced = headerElement.data('version-synced');
this.upstreamBlockId = upstreamBlockId;
this.upstreamBlockVersionSynced = upstreamBlockVersionSynced;
this.refreshFunction = refreshFunction;

this.render();
Expand Down
16 changes: 15 additions & 1 deletion cms/static/js/views/modals/select_v2_library_content.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ function($, _, gettext, BaseModal) {
this.disableActionButton('add');
}
}
if (event.data?.type === 'addSelectedComponentsToBank') {
this.selections = event.data.payload.selectedComponents;
this.callback(this.selections);
}
};
this.messageListener = window.addEventListener("message", handleMessage);
this.cleanupListener = () => { window.removeEventListener("message", handleMessage) };
Expand Down Expand Up @@ -70,10 +74,20 @@ function($, _, gettext, BaseModal) {
* Show a component picker modal from library.
* @param contentPickerUrl Url for component picker
* @param callback A function to call with the selected block(s)
* @param isIframeEmbed Boolean indicating if the unit is displayed inside an iframe
*/
showComponentPicker: function(contentPickerUrl, callback) {
showComponentPicker: function(contentPickerUrl, callback, isIframeEmbed) {
this.contentPickerUrl = contentPickerUrl;
this.callback = callback;
if (isIframeEmbed) {
window.parent.postMessage(
{
type: 'showMultipleComponentPicker',
payload: {}
}, document.referrer
);
return true;
}

this.render();
this.show();
Expand Down
Loading

0 comments on commit b80ed2f

Please sign in to comment.