-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
Don't use OLX when copying/duplicating blocks [FC-0049] #34386
Don't use OLX when copying/duplicating blocks [FC-0049] #34386
Conversation
Thanks for the pull request, @pomegranited! Please note that it may take us up to several weeks or months to complete a review and merge your PR. Feel free to add as much of the following information to the ticket as you can:
All technical communication about the code itself will be done via the GitHub pull request interface. As a reminder, our process documentation is here. Please let us know once your PR is ready for our review and all tests are green. |
ff8b6b5
to
9ec8727
Compare
instead of using TaggedBlockMixin.studio_post_duplicate Adds api.copy_tags method and tests to support this.
to avoid duplicating logic. This required updating get_all_object_tags to accept ordinary ContentKey object_ids, not just Course or Library keys.
793c7a7
to
261021c
Compare
992187e
to
3abe3c3
Compare
Adds a new JSON field to StagedContent to store a dict of serialized object tags from the copied block and its children, if any. These tags are deserialized and applied to the new block(s) on paste. To support this, we had to make 2 changes to XBlockSerializer: * XBlockSerializer now serializes the block's (and it's child block's) tags into a dict, keyed off the block usage key. These serialized tags are stored in StagedContent.tags * XBlockSerializer now inserts a url_name attribute when serializing blocks that don't provide one. When pasting serialized blocks, the url_name is used to reconstruct the original usage keys of any serialized children, so we can identify their tags. Other related changes: * Updates import_staged_content_from_user_clipboard's helper method to reconstruct child usage keys, so we can determine which tags apply to the pasted block(s). * Updates ClipboardPasteTestCase to test copying child tags * Removes TaggedBlockMixin, and moves its object tag serialization logic into content_tagging.api
42843b5
to
7702971
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pomegranited Great work on this! After looking into the code, it's alot more clear to me why this approach is much cleaner than the previous one storing tags in the OLX.
Just had a small nit (in addition to addressing the failing tests). I've tested out the functionality as described, everything worked really well. I did face an error when I tried duplicating a unit that contained a library block (but I think you mentioned that you're still getting to that), here's the error message to give you some insights:
2024-03-25 06:18:18,154 ERROR 128 [django.request] [user None] [ip None] log.py:241 - Internal Server Error: /xblock/
Traceback (most recent call last):
File "/openedx/edx-platform/xmodule/library_content_block.py", line 185, in source_library_key
return LibraryLocator.from_string(self.source_library_id)
File "/openedx/venv/lib/python3.8/site-packages/opaque_keys/__init__.py", line 183, in from_string
raise InvalidKeyError(cls, serialized)
opaque_keys.InvalidKeyError: <class 'opaque_keys.edx.locator.LibraryLocator'>: None
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/views/decorators/http.py", line 43, in inner
return func(request, *args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapper_view
return view_func(request, *args, **kwargs)
File "/openedx/edx-platform/common/djangoapps/util/json_request.py", line 57, in parse_json_into_request
return view_function(request, *args, **kwargs)
File "/openedx/edx-platform/cms/djangoapps/contentstore/views/block.py", line 140, in xblock_handler
return handle_xblock(request, usage_key_string)
File "/openedx/edx-platform/cms/djangoapps/contentstore/xblock_storage_handlers/view_handlers.py", line 227, in handle_xblock
dest_usage_key = duplicate_block(
File "/openedx/edx-platform/cms/djangoapps/contentstore/utils.py", line 1137, in duplicate_block
dupe = duplicate_block(dest_block.location, child, user=user, is_child=True)
File "/openedx/edx-platform/cms/djangoapps/contentstore/utils.py", line 1130, in duplicate_block
children_handled = dest_block.studio_post_duplicate(store, source_item)
File "/openedx/edx-platform/xmodule/library_content_block.py", line 599, in studio_post_duplicate
self._validate_sync_permissions()
File "/openedx/edx-platform/xmodule/library_content_block.py", line 518, in _validate_sync_permissions
if self.source_library_key:
File "/openedx/edx-platform/xmodule/library_content_block.py", line 187, in source_library_key
return LibraryLocatorV2.from_string(self.source_library_id)
File "/openedx/venv/lib/python3.8/site-packages/opaque_keys/__init__.py", line 183, in from_string
raise InvalidKeyError(cls, serialized)
opaque_keys.InvalidKeyError: <class 'opaque_keys.edx.locator.LibraryLocatorV2'>: None
[25/Mar/2024 06:18:18] "POST /xblock/ HTTP/1.1" 500 305190
to avoid circular imports when using these APIs.
and use taxonomy.id instead of taxonomy.external_id. To achieve this without adding functions to content_tagging.api, these related changes were made: * get_all_object_tags: now returns a list of tag values instead of ObjectTag instances, grouped by object_id and Taxonomy.id * set_object_tags: renamed to `set_all_object_tags`, to clarify its relationship to get_all_object_tags * set_all_object_tags: now accepts a list of tag values grouped by Taxonomy.id, instead of by Taxonomy.external_id * tag_object: added a content_tagging version of this oel_tagging method which checks that the given taxonomy is enabled for the given object_id's org before applying the tag. * types.ObjectTagByObjectIdDict changed to be TagValuesByObjectIdDict, types.ObjectTagByTaxonomyIdDict changed to be TagValuesByTaxonomyIdDict
1a76c60
to
61b3c57
Compare
Hi @yusuf-musleh , this PR is ready for a full review now. The error you found happens when the library content block doesn't have its
The Course Authoring MFE doesn't let me edit content library blocks, so I'm not able to verify that providing a valid library key here fixes the issue. But I'm pretty sure it doesn't have anything to do with tagging or the changes I've made here? But I can submit another PR to raise a better error here, if it's important to fix right away. |
61b3c57
to
c0b1412
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pomegranited Looks good to me 👍 great work!
The error you found happens when the library content block doesn't have its source_library_id set, which users have to do in the Studio/course authoring MFE
Thanks for looking into it, you're right the error seems unrelated to the changes here, and I think it's fine leaving it for another ticket/PR.
- I tested this: I following the testing instructions and confirmed everything is working well as expected
- I read through the code
-
I checked for accessibility issues -
Includes documentation -
I made sure any change in configuration variables is reflected in the corresponding client'sconfiguration-secure
repository.
instead of constructing a CourseKey.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great - just a couple small questions
Thank you for your review @bradenmacdonald ! I think I've addressed everything, but let me know if not? |
@pomegranited 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future. |
2U Release Notice: This PR has been deployed to the edX staging environment in preparation for a release to production. |
2U Release Notice: This PR has been deployed to the edX production environment. |
1 similar comment
2U Release Notice: This PR has been deployed to the edX production environment. |
Description
Refactors the block/library copy/paste and duplicate functions to ensure that content tags are copy/pasted/duplicated to use signals/events to trigger copying tags instead of using the OLX as intermediate storage.
Supporting information
Closes openedx/modular-learning#203
Testing instructions
USE latest master:
USE this branch:
Run migrations
Paste the block you copied into your course.
Ensure the paste works without errors, and creates the expected content.
Note that no tags will be pasted though.
Copy your tagged unit again.
Paste the tagged unit.
Check that the tags pasted as expected in the parent and all the different types of blocks.
Duplicate a subsection/unit.
Check that the tags duplicated as expected in the parent and child blocks.
Deadline
Need to get this merged before Redwood is cut to avoid OLX incompatibilities in exported courses or staged content.
Private-ref: FAL-3688