feat: add discussions context to course blocks API (#29300)
Add a new course blocks transformer that adds discussion context for units.
This commit is contained in:
@@ -106,7 +106,6 @@ class BlockStructureTransformer:
|
||||
block structure that is to be modified with collected
|
||||
data to be cached for the transformer.
|
||||
"""
|
||||
pass # lint-amnesty, pylint: disable=unnecessary-pass
|
||||
|
||||
@abstractmethod
|
||||
def transform(self, usage_info, block_structure):
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
"""
|
||||
Tests for discussions course block transformer
|
||||
"""
|
||||
|
||||
from lms.djangoapps.course_blocks.api import get_course_blocks
|
||||
from lms.djangoapps.course_blocks.transformers.tests.helpers import TransformerRegistryTestMixin
|
||||
from openedx.core.djangoapps.discussions.models import DEFAULT_PROVIDER_TYPE, DiscussionTopicLink
|
||||
from openedx.core.djangoapps.discussions.transformers import DiscussionsTopicLinkTransformer
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_SPLIT_MODULESTORE
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
|
||||
class DiscussionsTopicLinkTransformerTestCase(TransformerRegistryTestMixin, ModuleStoreTestCase):
|
||||
"""
|
||||
Tests behaviour of BlockCompletionTransformer
|
||||
"""
|
||||
TRANSFORMER_CLASS_TO_TEST = DiscussionsTopicLinkTransformer
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.test_topic_id = 'test-topic-id'
|
||||
self.course = CourseFactory.create()
|
||||
section = ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
category="chapter",
|
||||
)
|
||||
subsection1 = ItemFactory.create(
|
||||
parent_location=section.location,
|
||||
category="sequential",
|
||||
)
|
||||
self.discussable_unit = ItemFactory.create(
|
||||
parent_location=subsection1.location,
|
||||
category="vertical",
|
||||
# This won't really be used, but set it anyway
|
||||
discussion_enabled=True,
|
||||
)
|
||||
DiscussionTopicLink.objects.create(
|
||||
context_key=self.course.id,
|
||||
usage_key=self.discussable_unit.location,
|
||||
title=self.discussable_unit.display_name,
|
||||
provider_id=DEFAULT_PROVIDER_TYPE,
|
||||
external_id=self.test_topic_id,
|
||||
)
|
||||
self.non_discussable_unit = ItemFactory.create(
|
||||
parent_location=subsection1.location,
|
||||
category="vertical",
|
||||
discussion_enabled=False,
|
||||
)
|
||||
|
||||
def test_transform_aggregators(self):
|
||||
"""
|
||||
Tests that a unit that has a discussion topic link created will return the link
|
||||
and topic id in the course block data.
|
||||
"""
|
||||
block_structure = get_course_blocks(self.user, self.course.location, self.transformers)
|
||||
|
||||
embed_url = block_structure.get_xblock_field(
|
||||
self.discussable_unit.location,
|
||||
self.TRANSFORMER_CLASS_TO_TEST.EMBED_URL,
|
||||
)
|
||||
assert embed_url == f"http://discussions-mfe/discussions/{self.course.id}/topics/{self.test_topic_id}"
|
||||
|
||||
external_id = block_structure.get_xblock_field(
|
||||
self.discussable_unit.location,
|
||||
self.TRANSFORMER_CLASS_TO_TEST.EXTERNAL_ID,
|
||||
)
|
||||
assert external_id == self.test_topic_id
|
||||
|
||||
embed_url = block_structure.get_xblock_field(
|
||||
self.non_discussable_unit.location,
|
||||
self.TRANSFORMER_CLASS_TO_TEST.EMBED_URL,
|
||||
)
|
||||
assert embed_url is None
|
||||
|
||||
external_id = block_structure.get_xblock_field(
|
||||
self.non_discussable_unit.location,
|
||||
self.TRANSFORMER_CLASS_TO_TEST.EXTERNAL_ID,
|
||||
)
|
||||
assert external_id is None
|
||||
49
openedx/core/djangoapps/discussions/transformers.py
Normal file
49
openedx/core/djangoapps/discussions/transformers.py
Normal file
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
Discussions Topic Link Transformer
|
||||
"""
|
||||
|
||||
from openedx.core.djangoapps.content.block_structure.transformer import BlockStructureTransformer
|
||||
from openedx.core.djangoapps.discussions.models import DiscussionTopicLink, DiscussionsConfiguration
|
||||
from openedx.core.djangoapps.discussions.url_helpers import get_discussions_mfe_topic_url
|
||||
|
||||
|
||||
class DiscussionsTopicLinkTransformer(BlockStructureTransformer):
|
||||
"""
|
||||
A transformer that adds discussion topic context to the xblock.
|
||||
"""
|
||||
WRITE_VERSION = 1
|
||||
READ_VERSION = 1
|
||||
EXTERNAL_ID = "discussions_id"
|
||||
EMBED_URL = "discussions_url"
|
||||
|
||||
@classmethod
|
||||
def name(cls):
|
||||
"""
|
||||
Unique identifier for the transformer's class;
|
||||
same identifier used in setup.py.
|
||||
"""
|
||||
return "discussions_link"
|
||||
|
||||
def transform(self, usage_info, block_structure):
|
||||
"""
|
||||
loads override data into blocks
|
||||
"""
|
||||
provider_type = DiscussionsConfiguration.get(usage_info.course_key).provider_type
|
||||
topic_links = DiscussionTopicLink.objects.filter(
|
||||
context_key=usage_info.course_key,
|
||||
provider_id=provider_type,
|
||||
enabled_in_context=True,
|
||||
)
|
||||
for topic_link in topic_links:
|
||||
block_structure.override_xblock_field(
|
||||
topic_link.usage_key,
|
||||
DiscussionsTopicLinkTransformer.EXTERNAL_ID,
|
||||
topic_link.external_id,
|
||||
)
|
||||
mfe_embed_link = get_discussions_mfe_topic_url(usage_info.course_key, topic_link.external_id)
|
||||
if mfe_embed_link:
|
||||
block_structure.override_xblock_field(
|
||||
topic_link.usage_key,
|
||||
DiscussionsTopicLinkTransformer.EMBED_URL,
|
||||
mfe_embed_link,
|
||||
)
|
||||
35
openedx/core/djangoapps/discussions/url_helpers.py
Normal file
35
openedx/core/djangoapps/discussions/url_helpers.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
Helps for building discussions URLs
|
||||
"""
|
||||
from django.conf import settings
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
|
||||
def get_discussions_mfe_url(course_key: CourseKey) -> str:
|
||||
"""
|
||||
Returns the url for discussions for the specified course in the discussions MFE.
|
||||
|
||||
Args:
|
||||
course_key (CourseKey): course key of course for which to get url
|
||||
|
||||
Returns:
|
||||
(str) URL link for MFE. Empty if the base url isn't configured
|
||||
"""
|
||||
if settings.DISCUSSIONS_MICROFRONTEND_URL is not None:
|
||||
return f"{settings.DISCUSSIONS_MICROFRONTEND_URL}/discussions/{course_key}/"
|
||||
return ''
|
||||
|
||||
|
||||
def get_discussions_mfe_topic_url(course_key: CourseKey, topic_id: str) -> str:
|
||||
"""
|
||||
Returns the url for discussions for the specified course and topic in the discussions MFE.
|
||||
|
||||
Args:
|
||||
course_key (CourseKey): course key of course for which to get url
|
||||
|
||||
Returns:
|
||||
(str) URL link for MFE. Empty if the base url isn't configured
|
||||
"""
|
||||
if settings.DISCUSSIONS_MICROFRONTEND_URL is not None:
|
||||
return f"{get_discussions_mfe_url(course_key)}topics/{topic_id}"
|
||||
return ''
|
||||
Reference in New Issue
Block a user