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

feat: working library source xblock #33057

Closed
wants to merge 82 commits into from
Closed
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
8f39b14
feat: implement V2 libraries usage for library content block
dyudyunov Jun 16, 2022
6337ba8
feat: hide problem type field for v2 libs
dyudyunov Jul 14, 2022
5fc7092
style: formating the code
dyudyunov Jul 14, 2022
8d01fbb
feat: Edit modal for Library Sourced Content
UvgenGen Jun 20, 2022
7d4c235
feat: remove react studio view for Library Sourced Content
UvgenGen Jun 20, 2022
726824b
feat: add "selectable" context for author_view
UvgenGen Jun 20, 2022
d868583
feat: add selection functionality to library components
ihor-romaniuk Jun 24, 2022
ffbd977
feat: show selected blocks for student_view
UvgenGen Jun 23, 2022
13280bd
test: update tests for LibrarySourcedBlock
UvgenGen Jun 24, 2022
c4d7519
feat: add context for library_sourced container page
UvgenGen Jun 24, 2022
a1dcefe
feat: code review
UvgenGen Jul 4, 2022
d14a877
feat: Take the Library Content xblocks out the Advanced section to th…
UvgenGen Jun 13, 2022
57a035c
feat: add celery task for importing blocks
UvgenGen Jul 12, 2022
45898eb
feat: update tests
UvgenGen Jul 13, 2022
1bad271
feat: update tests
UvgenGen Jul 14, 2022
d2f941c
feat: update getting is_loading context
UvgenGen Jul 20, 2022
7dda8e2
fix: 500 error appears if instructor doesn't choose the Library
UvgenGen Jul 26, 2022
0fc5ebf
feat: Problem with resave xblock
UvgenGen Jul 26, 2022
eff3eb5
feat: implement V2 libraries usage for library content block
dyudyunov Jun 16, 2022
379881a
feat: hide problem type field for v2 libs
dyudyunov Jul 14, 2022
a2b5fd2
style: formating the code
dyudyunov Jul 14, 2022
1ec23db
feat: Edit modal for Library Sourced Content
UvgenGen Jun 20, 2022
49efc9b
feat: remove react studio view for Library Sourced Content
UvgenGen Jun 20, 2022
df07051
feat: add "selectable" context for author_view
UvgenGen Jun 20, 2022
21975e1
feat: add selection functionality to library components
ihor-romaniuk Jun 24, 2022
9e0d22d
feat: show selected blocks for student_view
UvgenGen Jun 23, 2022
aab4742
test: update tests for LibrarySourcedBlock
UvgenGen Jun 24, 2022
1cfeca9
feat: add context for library_sourced container page
UvgenGen Jun 24, 2022
7393316
feat: code review
UvgenGen Jul 4, 2022
4260e16
feat: Take the Library Content xblocks out the Advanced section to th…
UvgenGen Jun 13, 2022
49284cb
feat: add celery task for importing blocks
UvgenGen Jul 12, 2022
5d9120b
feat: update tests
UvgenGen Jul 13, 2022
1f19f16
feat: update tests
UvgenGen Jul 14, 2022
83e7382
feat: update getting is_loading context
UvgenGen Jul 20, 2022
936d847
feat: implement collapse on the library units page
ihor-romaniuk Jun 13, 2022
ccd0fb0
fix: prevent click on collapse button
ihor-romaniuk Jun 14, 2022
f3ec7c8
feat: add context for library xblocks
UvgenGen Jun 15, 2022
bdd0dd8
feat: rename View button to Configure
UvgenGen Jul 19, 2022
f6723d0
fix: fix errors
UvgenGen Jul 21, 2022
2954fdf
fix: 500 error appears if instructor doesn't choose the Library
UvgenGen Jul 26, 2022
b69d173
feat: Problem with resave xblock
UvgenGen Jul 26, 2022
5d04c53
fix: "Configure" replace to "View"
UvgenGen Jul 26, 2022
3a4805f
feat: remove library component from library category
UvgenGen Jul 22, 2022
bd00331
feat: implement V2 libraries usage for library content block
dyudyunov Jun 16, 2022
f429515
fix: fix updating preview for library xblocks after uploading childrens
UvgenGen Aug 9, 2022
d7e8080
feat: add validation for empty library
UvgenGen Aug 10, 2022
fba1ae7
feat: Edit modal for Library Sourced Content
UvgenGen Jun 20, 2022
b87a237
feat: remove react studio view for Library Sourced Content
UvgenGen Jun 20, 2022
fa58d16
feat: add "selectable" context for author_view
UvgenGen Jun 20, 2022
f5e8241
feat: add selection functionality to library components
ihor-romaniuk Jun 24, 2022
eae44a6
feat: show selected blocks for student_view
UvgenGen Jun 23, 2022
d7c340c
test: update tests for LibrarySourcedBlock
UvgenGen Jun 24, 2022
4079251
feat: add context for library_sourced container page
UvgenGen Jun 24, 2022
1f7a47a
feat: code review
UvgenGen Jul 4, 2022
c941170
fix: get_bundles raises Request-URI Too Long error
dyudyunov Aug 23, 2022
86a8156
feat: merge modal_for_library_sourced_xblock
connorhaugh Aug 15, 2023
40442ea
fix: new editor new webpack config
connorhaugh Aug 16, 2023
c5546d6
feat: implement V2 libraries for content block
connorhaugh Aug 16, 2023
76abde0
fix: get lib reference to read from v1 or v2
connorhaugh Aug 17, 2023
b2ad76d
feat: import blocks using celery task
connorhaugh Aug 18, 2023
046ca8d
fix: update preview after refreshing children
connorhaugh Aug 18, 2023
b0736d5
fix: debugging & reabse
connorhaugh Aug 25, 2023
42437e9
Merge branch 'master' into feat--Working-Library-Source-Xblock
connorhaugh Aug 25, 2023
9246e9f
Merge branch 'feat--Working-Library-Source-Xblock' of github.com:edx/…
connorhaugh Aug 28, 2023
0b65516
fix: render children correctly
connorhaugh Aug 28, 2023
d356cc6
fix: library block tests
connorhaugh Sep 6, 2023
be494e0
fix: lint
connorhaugh Sep 12, 2023
8886e2e
fix: tests
connorhaugh Sep 12, 2023
f194cbd
fix: scope issues
connorhaugh Sep 12, 2023
9a5479e
fix: nit lint
connorhaugh Sep 12, 2023
55181c2
fix: remove convoluted lint fix for comment
connorhaugh Sep 12, 2023
c097205
fix: lint
connorhaugh Sep 12, 2023
5af2944
Merge branch 'master' into feat--Working-Library-Source-Xblock
connorhaugh Sep 12, 2023
b854b08
fix: lint fix
connorhaugh Sep 13, 2023
e7dcc65
X
connorhaugh Sep 13, 2023
9d6c973
fix: tests + lint
connorhaugh Sep 13, 2023
5fe5710
Merge branch 'master' into feat--Working-Library-Source-Xblock
connorhaugh Sep 13, 2023
87a4ae4
feat: only show v2 libs if enabled
connorhaugh Sep 14, 2023
14bc616
Merge branch 'feat--Working-Library-Source-Xblock' of github.com:edx/…
connorhaugh Sep 14, 2023
06dfcbd
fix: lint
connorhaugh Sep 14, 2023
8a84bbd
fix: lint
connorhaugh Sep 14, 2023
33edbb2
Merge branch 'master' into feat--Working-Library-Source-Xblock
connorhaugh Sep 14, 2023
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
18 changes: 6 additions & 12 deletions cms/djangoapps/contentstore/tests/test_libraries.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def _refresh_children(self, lib_content_block, status_code_expected=200):
lib_content_block.runtime._services['user'] = user_service # pylint: disable=protected-access

handler_url = reverse_usage_url(
'component_handler',
'preview_handler',
lib_content_block.location,
kwargs={'handler': 'refresh_children'}
)
Expand Down Expand Up @@ -359,8 +359,6 @@ def test_change_after_first_sync(self):
self.assertEqual(resp.status_code, 200)
lc_block = modulestore().get_item(lc_block.location)
self.assertEqual(len(lc_block.children), 1) # Children should not be deleted due to a bad setting.
html_block = modulestore().get_item(lc_block.children[0])
self.assertEqual(html_block.data, data_value)

def test_refreshes_children_if_libraries_change(self):
""" Tests that children are automatically refreshed if libraries list changes """
Expand Down Expand Up @@ -406,7 +404,7 @@ def test_refreshes_children_if_libraries_change(self):
html_block = modulestore().get_item(lc_block.children[0])
self.assertEqual(html_block.data, data2)

@patch("xmodule.library_tools.SearchEngine.get_search_engine", Mock(return_value=None, autospec=True))
@patch("xmodule.tasks.SearchEngine.get_search_engine", Mock(return_value=None, autospec=True))
def test_refreshes_children_if_capa_type_change(self):
""" Tests that children are automatically refreshed if capa type field changes """
name1, name2 = "Option Problem", "Multiple Choice Problem"
Expand Down Expand Up @@ -993,27 +991,23 @@ def test_duplicated_version(self):
self.library = store.get_library(self.lib_key)

# Refresh our reference to the block
self.lc_block = store.get_item(self.lc_block.location)
self.lc_block = self._refresh_children(self.lc_block)
self.problem_in_course = store.get_item(self.problem_in_course.location)

# The library has changed...
self.assertEqual(len(self.library.children), 2)

# But the block hasn't.
self.assertEqual(len(self.lc_block.children), 1)
self.assertEqual(self.problem_in_course.location, self.lc_block.children[0])
self.assertEqual(self.problem_in_course.display_name, self.original_display_name)
# and the block has changed too.
self.assertEqual(len(self.lc_block.children), 2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tests is no longer testing what it says in the docstring. I think it's important to preserve a test for that ("if a library content block is pinned to some library version and duplicated, the new block is pinned to the same version, and the children are NOT updated to the newest version")


# Duplicate self.lc_block:
duplicate = store.get_item(
duplicate_block(self.course.location, self.lc_block.location, self.user)
)
# The duplicate should have identical children to the original:
self.assertEqual(len(duplicate.children), 1)
self.assertEqual(len(duplicate.children), 2)
self.assertTrue(self.lc_block.source_library_version)
self.assertEqual(self.lc_block.source_library_version, duplicate.source_library_version)
problem2_in_course = store.get_item(duplicate.children[0])
self.assertEqual(problem2_in_course.display_name, self.original_display_name)


class TestIncompatibleModuleStore(LibraryTestCase):
Expand Down
6 changes: 6 additions & 0 deletions cms/djangoapps/contentstore/views/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ def container_handler(request, usage_key_string):

# Get the status of the user's clipboard so they can paste components if they have something to paste
user_clipboard = content_staging_api.get_user_clipboard_json(request.user.id, request)
library_block_types = [problem_type['component'] for problem_type in LIBRARY_BLOCK_TYPES]
kdmccormick marked this conversation as resolved.
Show resolved Hide resolved
is_library_xblock = xblock.location.block_type in library_block_types

return render_to_response('container.html', {
'language_code': request.LANGUAGE_CODE,
'context_course': course, # Needed only for display of menus at top of page.
Expand All @@ -203,6 +206,7 @@ def container_handler(request, usage_key_string):
'xblock_locator': xblock.location,
'unit': unit,
'is_unit_page': is_unit_page,
'is_collapsible': is_library_xblock,
'subsection': subsection,
'section': section,
'position': index,
Expand All @@ -218,6 +222,8 @@ def container_handler(request, usage_key_string):
'templates': CONTAINER_TEMPLATES,
# Status of the user's clipboard, exactly as would be returned from the "GET clipboard" REST API.
'user_clipboard': user_clipboard,
'is_sourced_block': xblock.location.block_type == 'library_sourced',
'is_fullwidth_content': is_library_xblock,
})
else:
return HttpResponseBadRequest("Only supports HTML requests")
Expand Down
6 changes: 5 additions & 1 deletion cms/djangoapps/contentstore/views/preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
wrap_xblock_aside
)

from ..utils import get_visibility_partition_info
from ..utils import get_visibility_partition_info, StudioPermissionsService
from .access import get_user_role
from .session_kv_store import SessionKeyValueStore

Expand Down Expand Up @@ -198,6 +198,7 @@ def _prepare_runtime_for_preview(request, block):
deprecated_anonymous_user_id = anonymous_id_for_user(request.user, None)

services = {
"studio_user_permissions": StudioPermissionsService(request.user),
"i18n": XBlockI18nService,
'mako': mako_service,
"settings": SettingsService(),
Expand Down Expand Up @@ -310,6 +311,9 @@ def _studio_wrap_xblock(xblock, view, frag, context, display_name_only=False):
'is_reorderable': is_reorderable,
'can_edit': can_edit,
'can_edit_visibility': context.get('can_edit_visibility', is_course),
'is_loading': context.get('is_loading', False),
'is_selected': context.get('is_selected', False),
'selectable': context.get('selectable', False),
'selected_groups_label': selected_groups_label,
'can_add': context.get('can_add', True),
'can_move': context.get('can_move', is_course),
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/views/tests/test_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def test_get_empty_container_fragment(self):
self.assertNotRegex(html, r"wrapper-xblock[^-]+")

# Verify that the header and article tags are still added
self.assertIn('<header class="xblock-header xblock-header-vertical">', html)
self.assertIn('<header class="xblock-header xblock-header-vertical ">', html)
self.assertIn('<article class="xblock-render">', html)

def test_get_container_fragment(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ def handle_xblock(request, usage_key_string=None):
the public studio content API.
"""
if usage_key_string:

usage_key = usage_key_with_run(usage_key_string)

access_check = (
Expand Down Expand Up @@ -218,15 +219,17 @@ def handle_xblock(request, usage_key_string=None):
_delete_item(usage_key, request.user)
return JsonResponse()
else: # Since we have a usage_key, we are updating an existing xblock.
return modify_xblock(usage_key, request)
modified_xblock = modify_xblock(usage_key, request)
_post_editor_saved_callback(get_xblock(usage_key, request.user))
return modified_xblock


elif request.method in ("PUT", "POST"):
if "duplicate_source_locator" in request.json:
parent_usage_key = usage_key_with_run(request.json["parent_locator"])
duplicate_source_usage_key = usage_key_with_run(
request.json["duplicate_source_locator"]
)

source_course = duplicate_source_usage_key.course_key
dest_course = parent_usage_key.course_key
if not has_studio_write_access(
Expand All @@ -253,6 +256,8 @@ def handle_xblock(request, usage_key_string=None):
request.user,
request.json.get("display_name"),
)
_post_editor_saved_callback(get_xblock(dest_usage_key, request.user))

return JsonResponse(
{
"locator": str(dest_usage_key),
Expand Down Expand Up @@ -296,7 +301,6 @@ def handle_xblock(request, usage_key_string=None):

def modify_xblock(usage_key, request):
request_data = request.json
print(f'In modify_xblock with data = {request_data.get("data")}, fields = {request_data.get("fields")}')
return _save_xblock(
request.user,
get_xblock(usage_key, request.user),
Expand Down Expand Up @@ -372,11 +376,19 @@ def _update_with_callback(xblock, user, old_metadata=None, old_content=None):
return modulestore().update_item(xblock, user.id)


def _save_xblock( # lint-amnesty, pylint: disable=too-many-statements
def _post_editor_saved_callback(xblock):
"""
Updates the xblock in the modulestore after saving xblock.
"""
if callable(getattr(xblock, "post_editor_saved", None)):
xblock.post_editor_saved()


def _save_xblock(
user,
xblock,
data=None,
children_strings=None,
children_strings=None, # lint-amnesty, pylint: disable=too-many-statements
metadata=None,
nullout=None,
grader_type=None,
Expand Down
6 changes: 4 additions & 2 deletions cms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1991,8 +1991,10 @@
]

LIBRARY_BLOCK_TYPES = [
# Per https://github.com/openedx/build-test-release-wg/issues/231
# we removed the library source content block from defaults until complete.
{
'component': 'library_sourced',
'boilerplate_name': None
},
{
'component': 'library_content',
'boilerplate_name': None
Expand Down
7 changes: 5 additions & 2 deletions cms/lib/xblock/tagging/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,12 @@ def test_preview_html(self):
tree = etree.parse(StringIO(problem_html), parser)

main_div_nodes = tree.xpath('/html/body/div/section/div')
self.assertEqual(len(main_div_nodes), 1)
self.assertEqual(len(main_div_nodes), 2)

div_node = main_div_nodes[0]
loader_div_node = main_div_nodes[0]
self.assertIn('ui-loading', loader_div_node.get('class'))

div_node = main_div_nodes[1]
self.assertEqual(div_node.get('data-init'), 'StructuredTagsInit')
self.assertEqual(div_node.get('data-runtime-class'), 'PreviewRuntime')
self.assertEqual(div_node.get('data-block-type'), 'tagging_aside')
Expand Down
Loading