feat: Add blockType to xblockPreview & title to xblock_iframe [FC-0097] (#37362)
- Adds `blockType` and `is_modified` to the `showXBlockLibraryChangesPreview` iframe message. - Add title to the `xblock_iframe` - Add `is-modified` to `studio_xblock_wrapper` - Add `disable_staff_debug_info` as a query param in `render_xblock` - `downstream_is_modified` added to ComponentLink and ContainerLink
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.2.24 on 2025-09-23 19:47
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('contentstore', '0012_componentlink_top_level_parent_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='componentlink',
|
||||
name='downstream_is_modified',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='containerlink',
|
||||
name='downstream_is_modified',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
||||
@@ -108,6 +108,7 @@ class EntityLinkBase(models.Model):
|
||||
top_level_parent = models.ForeignKey("ContainerLink", on_delete=models.SET_NULL, null=True, blank=True)
|
||||
version_synced = models.IntegerField()
|
||||
version_declined = models.IntegerField(null=True, blank=True)
|
||||
downstream_is_modified = models.BooleanField(default=False)
|
||||
created = manual_date_time_field()
|
||||
updated = manual_date_time_field()
|
||||
|
||||
@@ -257,6 +258,7 @@ class ComponentLink(EntityLinkBase):
|
||||
version_synced: int,
|
||||
top_level_parent_usage_key: UsageKey | None = None,
|
||||
version_declined: int | None = None,
|
||||
downstream_is_modified: bool = False,
|
||||
created: datetime | None = None,
|
||||
) -> "ComponentLink":
|
||||
"""
|
||||
@@ -281,6 +283,7 @@ class ComponentLink(EntityLinkBase):
|
||||
'version_synced': version_synced,
|
||||
'version_declined': version_declined,
|
||||
'top_level_parent': top_level_parent,
|
||||
'downstream_is_modified': downstream_is_modified,
|
||||
}
|
||||
if upstream_block:
|
||||
new_values['upstream_block'] = upstream_block
|
||||
@@ -482,6 +485,7 @@ class ContainerLink(EntityLinkBase):
|
||||
version_synced: int,
|
||||
top_level_parent_usage_key: UsageKey | None = None,
|
||||
version_declined: int | None = None,
|
||||
downstream_is_modified: bool = False,
|
||||
created: datetime | None = None,
|
||||
) -> "ContainerLink":
|
||||
"""
|
||||
@@ -506,6 +510,7 @@ class ContainerLink(EntityLinkBase):
|
||||
'version_synced': version_synced,
|
||||
'version_declined': version_declined,
|
||||
'top_level_parent': top_level_parent,
|
||||
'downstream_is_modified': downstream_is_modified,
|
||||
}
|
||||
if upstream_container_id:
|
||||
new_values['upstream_container_id'] = upstream_container_id
|
||||
|
||||
@@ -384,6 +384,7 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_html1["id"],
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
@@ -400,7 +401,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_problem1["id"],
|
||||
'upstream_type': 'component'
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 3,
|
||||
@@ -417,7 +419,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_problem2["id"],
|
||||
'upstream_type': 'component'
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 1,
|
||||
@@ -434,7 +437,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_unit["id"],
|
||||
'upstream_type': 'container'
|
||||
'upstream_type': 'container',
|
||||
'downstream_is_modified': False,
|
||||
}
|
||||
]
|
||||
data = downstreams.json()
|
||||
@@ -533,6 +537,7 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_html1["id"],
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
@@ -549,7 +554,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_problem1["id"],
|
||||
'upstream_type': 'component'
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 3,
|
||||
@@ -566,7 +572,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_problem2["id"],
|
||||
'upstream_type': 'component'
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 1,
|
||||
@@ -583,7 +590,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_unit["id"],
|
||||
'upstream_type': 'container'
|
||||
'upstream_type': 'container',
|
||||
'downstream_is_modified': False,
|
||||
}
|
||||
]
|
||||
data = downstreams.json()
|
||||
@@ -681,6 +689,7 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_html1["id"],
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
@@ -697,7 +706,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_problem1["id"],
|
||||
'upstream_type': 'component'
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 4,
|
||||
@@ -714,7 +724,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': upstream_problem3["id"],
|
||||
'upstream_type': 'component'
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 1,
|
||||
@@ -731,7 +742,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_unit["id"],
|
||||
'upstream_type': 'container'
|
||||
'upstream_type': 'container',
|
||||
'downstream_is_modified': False,
|
||||
}
|
||||
]
|
||||
data = downstreams.json()
|
||||
@@ -810,6 +822,7 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_html1["id"],
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
@@ -826,7 +839,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_problem1["id"],
|
||||
'upstream_type': 'component'
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 4,
|
||||
@@ -843,7 +857,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': upstream_problem3["id"],
|
||||
'upstream_type': 'component'
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'id': 1,
|
||||
@@ -860,7 +875,8 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_unit["id"],
|
||||
'upstream_type': 'container'
|
||||
'upstream_type': 'container',
|
||||
'downstream_is_modified': False,
|
||||
}
|
||||
]
|
||||
data = downstreams.json()
|
||||
@@ -1047,6 +1063,7 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
Test that we can sync a html from a library into a course.
|
||||
"""
|
||||
# 1️⃣ First, create the html in the course, using the upstream problem as a template:
|
||||
date_format = self.now.isoformat().split("+")[0] + 'Z'
|
||||
downstream_html1 = self._create_block_from_upstream(
|
||||
block_category="html",
|
||||
parent_usage_key=str(self.course_subsection.usage_key),
|
||||
@@ -1079,6 +1096,34 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
>This is the HTML.</html>
|
||||
""")
|
||||
|
||||
# Check that: The downstream links are created as expected for the component
|
||||
downstreams = self._get_downstream_links(
|
||||
course_id=str(self.course.id)
|
||||
)
|
||||
expected_downstreams = [
|
||||
{
|
||||
'id': 1,
|
||||
'upstream_context_title': self.library_title,
|
||||
'upstream_version': 2,
|
||||
'ready_to_sync': False,
|
||||
'ready_to_sync_from_children': False,
|
||||
'upstream_context_key': self.library_id,
|
||||
'downstream_usage_key': downstream_html1["locator"],
|
||||
'downstream_context_key': str(self.course.id),
|
||||
'top_level_parent_usage_key': None,
|
||||
'version_synced': 2,
|
||||
'version_declined': None,
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_html1["id"],
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
]
|
||||
data = downstreams.json()
|
||||
self.assertEqual(data["count"], 1)
|
||||
self.assertListEqual(data["results"], expected_downstreams)
|
||||
|
||||
# 2️⃣ Now, lets modify the upstream html AND the downstream display_name:
|
||||
self._update_course_block_fields(downstream_html1["locator"], {
|
||||
"display_name": "New Text Content",
|
||||
@@ -1111,9 +1156,36 @@ class CourseToLibraryTestCase(ContentLibrariesRestApiTest, ModuleStoreTestCase):
|
||||
'version_declined': None,
|
||||
'ready_to_sync': True, # <--- updated
|
||||
'error_message': None,
|
||||
'is_modified': True,
|
||||
'is_modified': True, # <--- updated
|
||||
})
|
||||
|
||||
downstreams = self._get_downstream_links(
|
||||
course_id=str(self.course.id)
|
||||
)
|
||||
expected_downstreams = [
|
||||
{
|
||||
'id': 1,
|
||||
'upstream_context_title': self.library_title,
|
||||
'upstream_version': 3, # <--- updated
|
||||
'ready_to_sync': True, # <--- updated
|
||||
'ready_to_sync_from_children': False,
|
||||
'upstream_context_key': self.library_id,
|
||||
'downstream_usage_key': downstream_html1["locator"],
|
||||
'downstream_context_key': str(self.course.id),
|
||||
'top_level_parent_usage_key': None,
|
||||
'version_synced': 2,
|
||||
'version_declined': None,
|
||||
'created': date_format,
|
||||
'updated': date_format,
|
||||
'upstream_key': self.upstream_html1["id"],
|
||||
'upstream_type': 'component',
|
||||
'downstream_is_modified': True, # <--- updated
|
||||
},
|
||||
]
|
||||
data = downstreams.json()
|
||||
self.assertEqual(data["count"], 1)
|
||||
self.assertListEqual(data["results"], expected_downstreams)
|
||||
|
||||
# 3️⃣ Now, sync and check the resulting OLX of the downstream
|
||||
|
||||
self._sync_downstream(downstream_html1["locator"])
|
||||
|
||||
@@ -675,6 +675,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -692,6 +693,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -709,6 +711,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': str(self.top_level_downstream_unit.usage_key),
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -726,6 +729,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': str(self.top_level_downstream_chapter.usage_key),
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -743,6 +747,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -760,6 +765,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -777,6 +783,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -794,6 +801,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -811,6 +819,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -828,6 +837,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': str(self.top_level_downstream_chapter.usage_key),
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -845,6 +855,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': str(self.top_level_downstream_chapter.usage_key),
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
]
|
||||
self.assertListEqual(data["results"], expected)
|
||||
@@ -884,6 +895,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -901,6 +913,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -918,6 +931,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': str(self.top_level_downstream_unit.usage_key),
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -935,6 +949,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': str(self.top_level_downstream_chapter.usage_key),
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
]
|
||||
self.assertListEqual(data["results"], expected)
|
||||
@@ -969,6 +984,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -986,6 +1002,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1003,6 +1020,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1020,6 +1038,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1037,6 +1056,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1054,6 +1074,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': str(self.top_level_downstream_chapter.usage_key),
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1071,6 +1092,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': str(self.top_level_downstream_chapter.usage_key),
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
]
|
||||
self.assertListEqual(data["results"], expected)
|
||||
@@ -1170,6 +1192,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1187,6 +1210,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1204,6 +1228,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1221,6 +1246,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
]
|
||||
print(data["results"])
|
||||
@@ -1267,6 +1293,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1284,6 +1311,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1301,6 +1329,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
]
|
||||
self.assertListEqual(data["results"], expected)
|
||||
@@ -1354,6 +1383,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1371,6 +1401,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
{
|
||||
'created': date_format,
|
||||
@@ -1388,6 +1419,7 @@ class GetUpstreamViewTest(
|
||||
'version_declined': None,
|
||||
'version_synced': 1,
|
||||
'top_level_parent_usage_key': None,
|
||||
'downstream_is_modified': False,
|
||||
},
|
||||
]
|
||||
self.assertListEqual(data["results"], expected)
|
||||
|
||||
@@ -2426,6 +2426,7 @@ def _create_or_update_component_link(created: datetime | None, xblock):
|
||||
top_level_parent_usage_key=top_level_parent_usage_key,
|
||||
version_synced=xblock.upstream_version,
|
||||
version_declined=xblock.upstream_version_declined,
|
||||
downstream_is_modified=len(getattr(xblock, "downstream_customized", [])) > 0,
|
||||
created=created,
|
||||
)
|
||||
|
||||
@@ -2458,6 +2459,7 @@ def _create_or_update_container_link(created: datetime | None, xblock):
|
||||
version_synced=xblock.upstream_version,
|
||||
top_level_parent_usage_key=top_level_parent_usage_key,
|
||||
version_declined=xblock.upstream_version_declined,
|
||||
downstream_is_modified=len(getattr(xblock, "downstream_customized", [])) > 0,
|
||||
created=created,
|
||||
)
|
||||
|
||||
|
||||
@@ -577,6 +577,7 @@ function($, _, Backbone, gettext, BasePage,
|
||||
const headerElement = xblockElement.find('.xblock-header-primary');
|
||||
const upstreamBlockId = headerElement.data('upstream-ref');
|
||||
const upstreamBlockVersionSynced = headerElement.data('version-synced');
|
||||
const isLocallyModified = headerElement.data('is-modified');
|
||||
|
||||
try {
|
||||
if (this.options.isIframeEmbed) {
|
||||
@@ -586,9 +587,11 @@ function($, _, Backbone, gettext, BasePage,
|
||||
payload: {
|
||||
downstreamBlockId: xblockInfo.get('id'),
|
||||
displayName: xblockInfo.get('display_name'),
|
||||
isVertical: xblockInfo.isVertical(),
|
||||
isContainer: false,
|
||||
upstreamBlockId,
|
||||
upstreamBlockVersionSynced,
|
||||
isLocallyModified: isLocallyModified === 'True',
|
||||
blockType: xblockInfo.get('category'),
|
||||
}
|
||||
}, document.referrer
|
||||
);
|
||||
|
||||
@@ -470,6 +470,14 @@ body,
|
||||
&.xblock-iframe-content {
|
||||
height: 100%;
|
||||
|
||||
.xblock-title {
|
||||
margin-bottom: 1.5em !important;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
margin-block-start: 0.83em;
|
||||
margin-block-end: 0.83em;
|
||||
}
|
||||
|
||||
// Reset the max-height to allow the settings list to grow
|
||||
.wrapper-comp-settings .list-input.settings-list {
|
||||
max-height: unset;
|
||||
|
||||
@@ -93,6 +93,7 @@ can_unlink = upstream_info.upstream_ref and not upstream_info.has_top_level_pare
|
||||
% if upstream_info.upstream_ref:
|
||||
data-upstream-ref = ${upstream_info.upstream_ref}
|
||||
data-version-synced = ${upstream_info.version_synced}
|
||||
data-is-modified = ${upstream_info.is_modified}
|
||||
%endif
|
||||
>
|
||||
<div class="header-details">
|
||||
|
||||
@@ -196,6 +196,11 @@
|
||||
event listeners below, in certain situations. Resetting it to the default "auto" skirts the problem.-->
|
||||
<body style="background-color: white;" class="view-container">
|
||||
<div id="content" class="wrapper xblock-iframe-content">
|
||||
{% if show_title %}
|
||||
<div class="xblock-title">
|
||||
{{ display_name | safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- fragment body -->
|
||||
{{ fragment.body_html | safe }}
|
||||
<!-- fragment foot -->
|
||||
|
||||
@@ -47,6 +47,7 @@ from rest_framework import status
|
||||
from rest_framework.decorators import api_view, throttle_classes
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.throttling import UserRateThrottle
|
||||
from rest_framework.fields import BooleanField
|
||||
from web_fragments.fragment import Fragment
|
||||
from xmodule.course_block import (
|
||||
COURSE_VISIBILITY_PUBLIC,
|
||||
@@ -1576,6 +1577,9 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True, disable_sta
|
||||
Returns an HttpResponse with HTML content for the xBlock with the given usage_key.
|
||||
The returned HTML is a chromeless rendering of the xBlock (excluding content of the containing courseware).
|
||||
"""
|
||||
if not disable_staff_debug_info:
|
||||
disable_staff_debug_info = BooleanField().to_internal_value(request.GET.get('disable_staff_debug_info', False))
|
||||
|
||||
usage_key = UsageKey.from_string(usage_key_string)
|
||||
|
||||
usage_key = usage_key.replace(course_key=modulestore().fill_in_run(usage_key.course_key))
|
||||
|
||||
@@ -18,6 +18,7 @@ from rest_framework import permissions, serializers
|
||||
from rest_framework.decorators import api_view, permission_classes # lint-amnesty, pylint: disable=unused-import
|
||||
from rest_framework.exceptions import PermissionDenied, AuthenticationFailed, NotFound
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.fields import BooleanField
|
||||
from rest_framework.views import APIView
|
||||
from xblock.django.request import DjangoWebobRequest, webob_to_django_response
|
||||
from xblock.exceptions import NoSuchUsage
|
||||
@@ -100,6 +101,10 @@ def embed_block_view(request, usage_key: UsageKeyV2, view_name: str):
|
||||
Unstable - may change after Sumac
|
||||
"""
|
||||
# Check if a specific version has been requested. TODO: move this to a URL path param like the other views?
|
||||
show_title = request.GET.get('show_title', False)
|
||||
if show_title is not None:
|
||||
show_title = BooleanField().to_internal_value(show_title)
|
||||
|
||||
try:
|
||||
version = VersionConverter().to_python(request.GET.get("version"))
|
||||
except ValueError as exc:
|
||||
@@ -147,6 +152,8 @@ def embed_block_view(request, usage_key: UsageKeyV2, view_name: str):
|
||||
'view_name': view_name,
|
||||
'is_development': settings.DEBUG,
|
||||
'oa_manifest': new_oa_manifest,
|
||||
'display_name': block.display_name,
|
||||
'show_title': show_title,
|
||||
}
|
||||
response = render(request, 'xblock_v2/xblock_iframe.html', context, content_type='text/html')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user