-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Support for syncing units from libraries to courses #36553
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
Support for syncing units from libraries to courses #36553
Conversation
|
Thanks for the pull request, @navinkarkera! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. DetailsWhere can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
5cc709d to
818d6c8
Compare
a2cfb06 to
647d733
Compare
5ffcfb2 to
d9e6e16
Compare
| notices = [] | ||
| # Store final children keys to update order of components in unit | ||
| children = [] | ||
| for i in range(len(upstream_children)): |
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.
Nit for later: we can use enumerate() here.
| if isinstance(upstream_key, LibraryUsageLocatorV2): | ||
| lib_block = sync_from_upstream_block(downstream=downstream, user=request.user) | ||
| static_file_notices = import_static_assets_for_library_sync(downstream, lib_block, request) | ||
| store.update_item(downstream, request.user.id) | ||
| else: |
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.
Nit for later: Probably worth pulling the container sync into a different function and having this one call that.
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.
I agree. Also, I want to move all the sync stuff into one upstream_sync app instead of having some key bits of the code randomly in xblock_storage_handlers (?) and the overloaded /xblock/ REST API endpoint.
| # This downstream block was added, or deleted from upstream block. | ||
| store.delete_item(child.usage_key, user_id=request.user.id) |
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.
Clarification: This is the part that (for the MVP) will delete any local additions to a Unit when the next upstream sync happens, right?
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.
Yes, this deletes two different things:
- local additions in the course - will get deleted on next sync
- blocks deleted upstream
| """ | ||
| syncable_fields = _get_synchronizable_fields(upstream, downstream) | ||
| customizable_fields = set(downstream.get_customizable_fields().keys()) | ||
| isVideoBlock = downstream.usage_key.block_type == "video" |
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.
Nit: I'm surprised our linting didn't complain about camel-cased var here.
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.
Fixed. But yeah, that's suspicious....
| # Note: if we expect that an upstream may not be set at all (i.e. we're just inspecting a random | ||
| # unit that may be a regular course unit), we don't want to log this, so set log_error=False then. | ||
| if log_error: |
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.
Simply viewing a regular unit in Studio (even before this PR) was resulting in a ton of these warnings:
upstream_sync.py:133 - Tried to inspect an unsupported, broken, or missing downstream->upstream link: 'block-v1:BradenX+CP200+23+type@vertical+block@9d1d7e5c0b4a42958f7e4174879ec1e2'->'None'
... cms.lib.xblock.upstream_sync.NoUpstream: Content is not linked to a Content Library.
So I updated the code to suppress the logging in general. Most things don't have an upstream so it's expected.
ormsbee
left a comment
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.
I have a lot of nits for follow-ups, but the only blocking concern I have in the short term is the part in the models.py file where it looks like we're always saying that there are changes:
@bradenmacdonald: If you've determined that this still gives us the correct behavior, then I'd really like to see some comment explaining what's going on. It's either a bug or it's really confusing in its current state.
ormsbee
left a comment
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.
I have a number of nits for follow-up, but nothing blocking.
I didn't really get into the But what I believe is going on here is this function is ultimately only ever called during The code is very confusing but I think what it's trying to say is this:
|
|
Thanks everyone who collaborated on this PR, @navinkarkera @pomegranited @ormsbee ! @navinkarkera can you please work on a follow-up PR(s) for some of the cleanups that @ormsbee has identified? |
|
2U Release Notice: This PR has been deployed to the edX staging environment in preparation for a release to production. |
@bradenmacdonald @ormsbee Sorry for this very confusing piece of code. You guessed it right @bradenmacdonald. At first, But while working on the frontend, I came across the requirement of sorting the links based on recently modified downstream blocks. XBlocks do not store modified dates so I updated this part to update the links modified time any time downstream block is updated and use it as base for sorting the links in frontend. |
|
@bradenmacdonald @ormsbee Created #36599 to address comments. |
If you need this from the modulestore, can you call |
|
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. |
|
Created openedx/frontend-app-authoring#1865 to compliment above change in frontend. |
* feat: library unit sync * feat: create component link only for component xblocks * feat: container link model * feat: update downstream api views * feat: delete extra components in container on sync (not working) * fix: duplicate definitions of LibraryXBlockMetadata * test: add a new integration test suite for syncing * feat: partially implement container+child syncing * fix: blockserializer wasn't always serializing all HTML block fields * feat: handle reorder, addition and deletion of components in sync Updates children components of unit in course based on upstream unit, deletes removed component, adds new ones and updates order as per upstream. * feat: return unit upstreamInfo and disallow edits to units in courses that are sourced from a library (#773) * feat: Add upstream_info to unit * feat: disallow edits to units in courses that are sourced from a library (#774) --------- Co-authored-by: Jillian Vogel <jill@opencraft.com> Co-authored-by: Rômulo Penido <romulo.penido@gmail.com> * docs: capitalization of XBlock Co-authored-by: David Ormsbee <dave@axim.org> * refactor: (minor) change python property name to reflect type better * fix: lots of "Tried to inspect a missing...upstream link" warnings when viewing a unit in Studio * docs: mention potential REST API for future refactor * fix: check if upstream actually exists before making unit read-only * chore: fix camel-case var * fix: test failure when mocked XBlock doesn't have UpstreamSyncMixin --------- Co-authored-by: Braden MacDonald <braden@opencraft.com> Co-authored-by: Chris Chávez <xnpiochv@gmail.com> Co-authored-by: Jillian Vogel <jill@opencraft.com> Co-authored-by: Rômulo Penido <romulo.penido@gmail.com> Co-authored-by: Braden MacDonald <mail@bradenm.com> Co-authored-by: David Ormsbee <dave@axim.org>
* feat: library unit sync * feat: create component link only for component xblocks * feat: container link model * feat: update downstream api views * feat: delete extra components in container on sync (not working) * fix: duplicate definitions of LibraryXBlockMetadata * test: add a new integration test suite for syncing * feat: partially implement container+child syncing * fix: blockserializer wasn't always serializing all HTML block fields * feat: handle reorder, addition and deletion of components in sync Updates children components of unit in course based on upstream unit, deletes removed component, adds new ones and updates order as per upstream. * feat: return unit upstreamInfo and disallow edits to units in courses that are sourced from a library (#773) * feat: Add upstream_info to unit * feat: disallow edits to units in courses that are sourced from a library (#774) --------- Co-authored-by: Jillian Vogel <jill@opencraft.com> Co-authored-by: Rômulo Penido <romulo.penido@gmail.com> * docs: capitalization of XBlock Co-authored-by: David Ormsbee <dave@axim.org> * refactor: (minor) change python property name to reflect type better * fix: lots of "Tried to inspect a missing...upstream link" warnings when viewing a unit in Studio * docs: mention potential REST API for future refactor * fix: check if upstream actually exists before making unit read-only * chore: fix camel-case var * fix: test failure when mocked XBlock doesn't have UpstreamSyncMixin --------- Co-authored-by: Braden MacDonald <braden@opencraft.com> Co-authored-by: Chris Chávez <xnpiochv@gmail.com> Co-authored-by: Jillian Vogel <jill@opencraft.com> Co-authored-by: Rômulo Penido <romulo.penido@gmail.com> Co-authored-by: Braden MacDonald <mail@bradenm.com> Co-authored-by: David Ormsbee <dave@axim.org>
Description
Sync unit containers from library to courses.
Private-ref: FAL-4077Test instructions:
Run the new integration tests, which should cover most things:
Manual Test instructions:
Use curl or any other tool to post request, NOTE: below example does not contain
csrftoken,studio_session_idetc. which you can add. TIP: use developer console to copy any request as curl request in browser.