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:
Kshitij Sobti
2021-12-07 06:10:48 +00:00
committed by GitHub
parent 51fe9b9da4
commit 9f4bc9900b
12 changed files with 196 additions and 14 deletions

View File

@@ -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):

View File

@@ -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

View 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,
)

View 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 ''