feat: allow editing imported text blocks (#37124)

* feat: allow editing html block imported from upstream

The modified field is left untouched in future sync while storing the
upstream values in hidden fields to allow authors to revert to upstream
version at any point.

* fix: sync downstream_customized field for copy-pasted modified block

* test: add more tests

* fix: lint issues

* test: copy paste

* feat: skip sync if html data is modified

* feat: update upstream fields only when modified

* refactor: use version_synced field to skip sync

* feat: edit title inplace for library source components

* fixup! feat: edit title inplace for library source components

* fix: edit title button style

* fix: test case

* fix: lint issue

* refactor: don't show different icon for modified upstream blocks

* Revert "refactor: use version_synced field to skip sync"

This reverts commit 8b784fff2f49b43702c952e7f955bd4048e8cc69.

* feat: only skip sync for modified blocks if updated as part of container

* refactor: update sync behaviour when synced individually and as part of parent

* feat: include ready to sync children info in downstream link get api

* test: fix failing tests

* fix: lint issues

* feat: new tests and update api to allow overriding modified fields in sync

* test: api changes

* refactor: edit options should be visible for individual imports

* docs: update api docs

* chore: remove old comments
This commit is contained in:
Navin Karkera
2025-09-17 14:50:24 +05:30
committed by GitHub
parent c27edbc578
commit a11086ffac
15 changed files with 862 additions and 291 deletions

View File

@@ -9,6 +9,7 @@ from lxml import etree
from opaque_keys.edx.locator import LibraryLocatorV2
from openedx.core.djangoapps.content_tagging.api import get_all_object_tags, TagValuesByObjectIdDict
from xmodule.xml_block import serialize_field
from .data import StaticFile
from . import utils
@@ -140,7 +141,7 @@ class XBlockSerializer:
if "top_level_downstream_parent_key" in block.fields \
and block.fields["top_level_downstream_parent_key"].is_set_on(block):
olx_node.attrib["top_level_downstream_parent_key"] = str(block.top_level_downstream_parent_key)
olx_node.attrib["top_level_downstream_parent_key"] = serialize_field(block.top_level_downstream_parent_key)
return olx_node
@@ -166,9 +167,10 @@ class XBlockSerializer:
if block.use_latex_compiler:
olx_node.attrib["use_latex_compiler"] = "true"
for field_name in block.fields:
if (field_name.startswith("upstream") or field_name == "top_level_downstream_parent_key") \
and block.fields[field_name].is_set_on(block):
olx_node.attrib[field_name] = str(getattr(block, field_name))
if (
field_name.startswith(("upstream", "downstream")) or field_name == "top_level_downstream_parent_key"
) and block.fields[field_name].is_set_on(block):
olx_node.attrib[field_name] = serialize_field(getattr(block, field_name))
# Escape any CDATA special chars
escaped_block_data = block.data.replace("]]>", "]]>")