diff --git a/cms/djangoapps/contentstore/rest_api/v2/views/downstreams.py b/cms/djangoapps/contentstore/rest_api/v2/views/downstreams.py index cf76c8b206d4..5079698082be 100644 --- a/cms/djangoapps/contentstore/rest_api/v2/views/downstreams.py +++ b/cms/djangoapps/contentstore/rest_api/v2/views/downstreams.py @@ -4,7 +4,7 @@ API paths (We will move these into proper api_doc_tools annotations soon https://github.com/openedx/edx-platform/issues/35653): - /api/v2/contentstore/downstreams/{usage_key_string} + /api/contentstore/v2/downstreams/{usage_key_string} GET: Inspect a single downstream block's link to upstream content. 200: Upstream link details successfully fetched. Returns UpstreamLink (may contain an error_message). @@ -26,7 +26,7 @@ 400: Content at upstream_ref does not support syncing. 404: Downstream block not found or user lacks permission to edit it. - /api/v2/contentstore/downstreams/{usage_key_string}/sync + /api/contentstore/v2/downstreams/{usage_key_string}/sync POST: Sync a downstream block with upstream content. 200: Downstream block successfully synced with upstream content. @@ -41,8 +41,8 @@ 404: Downstream block not found or user lacks permission to edit it. # NOT YET IMPLEMENTED -- Will be needed for full Libraries Relaunch in ~Teak. - /api/v2/contentstore/downstreams - /api/v2/contentstore/downstreams?course_id=course-v1:A+B+C&ready_to_sync=true + /api/contentstore/v2/downstreams + /api/contentstore/v2/downstreams?course_id=course-v1:A+B+C&ready_to_sync=true GET: List downstream blocks that can be synced, filterable by course or sync-readiness. 200: A paginated list of applicable & accessible downstream blocks. Entries are UpstreamLinks. diff --git a/cms/lib/xblock/upstream_sync.py b/cms/lib/xblock/upstream_sync.py index 8dbe672a5d10..62a4bd7f4aa6 100644 --- a/cms/lib/xblock/upstream_sync.py +++ b/cms/lib/xblock/upstream_sync.py @@ -223,10 +223,22 @@ def _load_upstream_link_and_block(downstream: XBlock, user: AbstractUser) -> tup def _update_customizable_fields(*, upstream: XBlock, downstream: XBlock, only_fetch: bool) -> None: """ - For each customizable field `downstream.blah`: + For each customizable field: + * Save the upstream value to a hidden field on the downstream ("FETCH"). + * If `not only_fetch`, and if the field *isn't* customized on the downstream, then: + * Update it the downstream field's value from the upstream field ("SYNC"). - 1. Fetch `upstream.blah` and save it in `downstream.upstream_blah`. - 2. If not only_fetch, and if `downstream.blah` isn't customized, update it from `upstream.blah`. + Concrete example: Imagine `lib_problem` is our upstream and `course_problem` is our downstream. + + * Say that the customizable fields are [display_name, max_attempts]. + + * Set `course_problem.upstream_display_name = lib_problem.display_name` ("fetch"). + * If `not only_fetch`, and `course_problem.display_name` wasn't customized, then: + * Set `course_problem.display_name = lib_problem.display_name` ("sync"). + + * Set `course_problem.upstream_max_attempts = lib_problem.max_attempts` ("fetch"). + * If `not only_fetch`, and `course_problem.max_attempts` wasn't customized, then: + * Set `course_problem.max_attempts = lib_problem.max_attempts` ("sync"). """ syncable_field_names = _get_synchronizable_fields(upstream, downstream) @@ -235,7 +247,7 @@ def _update_customizable_fields(*, upstream: XBlock, downstream: XBlock, only_fe if field_name not in syncable_field_names: continue - # Fetch the upstream's value and save it on the downstream (ie, `downstream.upstream_$FIELD`). + # FETCH the upstream's value and save it on the downstream (ie, `downstream.upstream_$FIELD`). old_upstream_value = getattr(downstream, fetch_field_name) new_upstream_value = getattr(upstream, field_name) setattr(downstream, fetch_field_name, new_upstream_value) @@ -257,7 +269,7 @@ def _update_customizable_fields(*, upstream: XBlock, downstream: XBlock, only_fe if old_upstream_value and downstream_value != old_upstream_value: continue # Field has been customized. Don't touch it. Move on. - # Field isn't customized -- update it! + # Field isn't customized -- SYNC it! setattr(downstream, field_name, new_upstream_value) @@ -295,10 +307,7 @@ def decline_sync(downstream: XBlock) -> None: If `downstream` lacks a valid+supported upstream link, this raises an UpstreamLinkException. """ - # Try to load the upstream. upstream_link = UpstreamLink.get_for_block(downstream) # Can raise UpstreamLinkException - if not upstream_link: - return # No upstream -> nothing to sync. downstream.upstream_version_declined = upstream_link.version_available