Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BD-14] feat: implement V2 libraries usage for library content block #30895

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions openedx/core/lib/blockstore_api/methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,18 @@ def delete_collection(collection_uuid):
@toggle_blockstore_api
def get_bundles(uuids=None, text_search=None):
"""
Get the details of all bundles
Get the details of all bundles.
"""
query_params = {}
data = {}
if uuids:
query_params['uuid'] = ','.join(map(str, uuids))
# Potentially we could have a lot of libraries which will lead to 414 error (Request-URI Too Long)
# if sending uuids in the query_params. So we have to use the request data instead.
data = {'uuid': ','.join(map(str, uuids))}
if text_search:
query_params['text_search'] = text_search
version_url = api_url('bundles') + '?' + urlencode(query_params)
response = api_request('get', version_url)
response = api_request('get', version_url, json=data)
# build bundle from response, convert map object to list and return
return [_bundle_from_response(item) for item in response]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* JavaScript for special editing operations that can be done on LibraryContentXBlock */
// This is a temporary UI improvements that will be removed when V2 content libraries became
// fully functional

/**
* Toggle the "Problem Type" settings section depending on selected library type.
* As for now, the V2 libraries don't support different problem types, so they can't be
* filtered by it. We're hiding the Problem Type field for them.
*/
function checkProblemTypeShouldBeVisible(editor) {
var libraries = editor.find('.wrapper-comp-settings.metadata_edit.is-active')
.data().metadata.source_library_id.options;
var selectedIndex = $("select[name='Library']", editor)[0].selectedIndex;
var libraryKey = libraries[selectedIndex].value;
var url = URI('/xblock')
.segment(editor.find('.xblock.xblock-studio_view.xblock-studio_view-library_content.xblock-initialized')
.data('usage-id'))
.segment('handler')
.segment('is_v2_library');

$.ajax({
type: 'POST',
url: url,
data: JSON.stringify({'library_key': libraryKey}),
success: function(data) {
var problemTypeSelect = editor.find("select[name='Problem Type']")
.parents("li.field.comp-setting-entry.metadata_entry");
data.is_v2 ? problemTypeSelect.hide() : problemTypeSelect.show();
}
});
}

/**
* Waits untill editor html loaded, than calls checks for Program Type field toggling.
*/
function waitForEditorLoading() {
var checkContent = setInterval(function() {
var $modal = $('.xblock-editor');
var content = $modal.html();
if (content) {
clearInterval(checkContent);
checkProblemTypeShouldBeVisible($modal);
}
}, 10);
}
// Initial call
waitForEditorLoading();

var $librarySelect = $("select[name='Library']");
$(document).on('change', $librarySelect, waitForEditorLoading)

var $libraryContentEditors = $('.xblock-header.xblock-header-library_content');
var $editBtns = $libraryContentEditors.find('.action-item.action-edit');
$(document).on('click', $editBtns, waitForEditorLoading)
38 changes: 30 additions & 8 deletions xmodule/library_content_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@
import random
from copy import copy
from gettext import ngettext
from rest_framework import status

import bleach
from django.conf import settings
from django.utils.functional import classproperty
from lazy import lazy
from lxml import etree
from lxml.etree import XMLSyntaxError
from opaque_keys.edx.locator import LibraryLocator
from opaque_keys import InvalidKeyError
from opaque_keys.edx.locator import LibraryLocator, LibraryLocatorV2
from pkg_resources import resource_string
from rest_framework import status
from web_fragments.fragment import Fragment
from webob import Response
from xblock.completable import XBlockCompletionMode
Expand All @@ -29,16 +30,15 @@
from xmodule.studio_editable import StudioEditableBlock
from xmodule.util.xmodule_django import add_webpack_to_fragment
from xmodule.validation import StudioValidation, StudioValidationMessage
from xmodule.xml_module import XmlMixin
from xmodule.x_module import (
STUDENT_VIEW,
HTMLSnippet,
ResourceTemplates,
shim_xmodule_js,
STUDENT_VIEW,
XModuleMixin,
XModuleToXBlockMixin,
shim_xmodule_js,
)

from xmodule.xml_module import XmlMixin

# Make '_' a no-op so we can scrape strings. Using lambda instead of
# `django.utils.translation.ugettext_noop` because Django cannot be imported in this file
Expand Down Expand Up @@ -189,9 +189,14 @@ def completion_mode(cls): # pylint: disable=no-self-argument
@property
def source_library_key(self):
"""
Convenience method to get the library ID as a LibraryLocator and not just a string
Convenience method to get the library ID as a LibraryLocator and not just a string.

Supports either library v1 or library v2 locators.
"""
return LibraryLocator.from_string(self.source_library_id)
try:
return LibraryLocator.from_string(self.source_library_id)
except InvalidKeyError:
return LibraryLocatorV2.from_string(self.source_library_id)

@classmethod
def make_selection(cls, selected, children, max_count, mode):
Expand Down Expand Up @@ -456,6 +461,7 @@ def studio_view(self, _context):
fragment = Fragment(
self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context())
)
fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/library_content_edit_helpers.js'))
add_webpack_to_fragment(fragment, 'LibraryContentBlockStudio')
shim_xmodule_js(fragment, self.studio_js_module_name)
return fragment
Expand Down Expand Up @@ -517,6 +523,22 @@ def refresh_children(self, request=None, suffix=None): # lint-amnesty, pylint:
self.tools.update_children(self, user_perms)
return Response()

@XBlock.json_handler
def is_v2_library(self, data, suffix=''): # lint-amnesty, pylint: disable=unused-argument
"""
Check the library version by library_id.

This is a temporary handler needed for hiding the Problem Type xblock editor field for V2 libraries.
"""
lib_key = data.get('library_key')
try:
LibraryLocatorV2.from_string(lib_key)
except InvalidKeyError:
is_v2 = False
else:
is_v2 = True
return {'is_v2': is_v2}

# Copy over any overridden settings the course author may have applied to the blocks.
def _copy_overrides(self, store, user_id, source, dest):
"""
Expand Down
Loading