fix: show correct icons in the sidebar for units with custom XBlocks

Currently, the sidebar relies only on the XBlock's `category` class attribute
(called `type` in the transformers). This behavior is inconsistent with the
legacy subsection navigation, which relies on the `XModuleMixin.get_icon_class`
method. This commit adds the `icon_class` to the fields collected by the
transformers and uses it to determine whether the "problem" or "video" icon
should be displayed for a unit in the sidebar.
This commit is contained in:
Agrendalath
2025-01-06 23:47:18 +01:00
committed by Farhaan Bukhsh
parent 64190d1e13
commit bbc0cc2baa
5 changed files with 46 additions and 2 deletions

View File

@@ -59,6 +59,7 @@ SUPPORTED_FIELDS = [
SupportedFieldType('weight'),
SupportedFieldType('show_correctness'),
SupportedFieldType('hide_from_toc'),
SupportedFieldType('icon_class'),
# 'student_view_data'
SupportedFieldType(StudentViewTransformer.STUDENT_VIEW_DATA, StudentViewTransformer),
# 'student_view_multi_device'

View File

@@ -54,7 +54,15 @@ class BlocksAPITransformer(BlockStructureTransformer):
transform method.
"""
# collect basic xblock fields
block_structure.request_xblock_fields('graded', 'format', 'display_name', 'category', 'due', 'show_correctness')
block_structure.request_xblock_fields(
'graded',
'format',
'display_name',
'category',
'due',
'show_correctness',
'icon_class',
)
# collect data from containing transformers
StudentViewTransformer.collect(block_structure)

View File

@@ -82,7 +82,11 @@ class CourseBlockSerializer(serializers.Serializer):
video
"""
children = block.get('children', [])
child_classes = {child.get('type') for child in children}
child_classes = {
value
for child in children
for value in (child.get('type'), child.get('icon_class'))
}
if 'problem' in child_classes:
return 'problem'
if 'video' in child_classes:

View File

@@ -870,3 +870,33 @@ class SidebarBlocksTestViews(BaseCourseHomeTests):
assert vertical_data['complete']
assert sequence_data['completion_stat'] == expected_sequence_completion_stat
assert vertical_data['completion_stat'] == expected_vertical_completion_stat
@ddt.data(
(['html'], 'other'),
(['html', 'video'], 'video'),
(['html', 'video', 'problem'], 'problem'),
)
@ddt.unpack
def test_vertical_icon(self, block_categories, expected_icon):
"""Test that the API checks the children `category` to determine the icon for the unit."""
self.add_blocks_to_course()
CourseEnrollment.enroll(self.user, self.course.id)
for category in block_categories:
BlockFactory.create(parent=self.vertical, category=category)
response = self.client.get(reverse('course-home:course-navigation', args=[self.course.id]))
vertical_data = response.data['blocks'][str(self.vertical.location)]
assert vertical_data['icon'] == expected_icon
@patch('xmodule.html_block.HtmlBlock.icon_class', 'video')
def test_vertical_icon_determined_by_icon_class(self):
"""Test that the API checks the children `icon_class` to determine the icon for the unit."""
self.add_blocks_to_course()
CourseEnrollment.enroll(self.user, self.course.id)
BlockFactory.create(parent=self.vertical, category='html')
response = self.client.get(reverse('course-home:course-navigation', args=[self.course.id]))
vertical_data = response.data['blocks'][str(self.vertical.location)]
assert vertical_data['icon'] == 'video'

View File

@@ -116,6 +116,7 @@ def get_course_outline_block_tree(request, course_id, user=None, allow_start_dat
'complete',
'resume_block',
'hide_from_toc',
'icon_class',
],
allow_start_dates_in_future=allow_start_dates_in_future,
)