feat: add share link button when hide from toc is enabled in sections (#34043)

* feat: add share link modal when hide from toc is enabled

Adds a new button in the child subsections of sections with Hide From TOC enabled.
This button displays a new modal with two tabs. The first tab displays a button
that allows you to copy the link of that subsection to the clipboard. The second
tab displays a button that allows you to copy the embedded link of the same
subsection to the clipboard.

Ref: https://openedx.atlassian.net/wiki/spaces/OEPM/pages/3853975595/Feature+Enhancement+Proposal+Hide+Sections+from+course+outline
This commit is contained in:
Bryann Valderrama
2024-03-07 13:12:17 -05:00
committed by GitHub
parent c848767369
commit 19bc5c802c
17 changed files with 516 additions and 11 deletions

View File

@@ -8,6 +8,7 @@ from lxml import etree
from mimetypes import guess_type
from attrs import frozen, Factory
from django.conf import settings
from django.utils.translation import gettext as _
from opaque_keys.edx.keys import AssetKey, CourseKey, UsageKey
from opaque_keys.edx.locator import DefinitionLocator, LocalId
@@ -22,6 +23,7 @@ from xmodule.modulestore.django import modulestore
from xmodule.xml_block import XmlMixin
from cms.djangoapps.models.settings.course_grading import CourseGradingModel
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
import openedx.core.djangoapps.content_staging.api as content_staging_api
from .utils import reverse_course_url, reverse_library_url, reverse_usage_url
@@ -125,6 +127,34 @@ def xblock_studio_url(xblock, parent_xblock=None, find_parent=False):
return reverse_usage_url('container_handler', xblock.location)
def xblock_lms_url(xblock) -> str:
"""
Returns the LMS URL for the specified xblock.
Args:
xblock: The xblock to get the LMS URL for.
Returns:
str: The LMS URL for the specified xblock.
"""
lms_root_url = configuration_helpers.get_value('LMS_ROOT_URL', settings.LMS_ROOT_URL)
return f"{lms_root_url}/courses/{xblock.location.course_key}/jump_to/{xblock.location}"
def xblock_embed_lms_url(xblock) -> str:
"""
Returns the LMS URL for the specified xblock in embed mode.
Args:
xblock: The xblock to get the LMS URL for.
Returns:
str: The LMS URL for the specified xblock in embed mode.
"""
lms_root_url = configuration_helpers.get_value('LMS_ROOT_URL', settings.LMS_ROOT_URL)
return f"{lms_root_url}/xblock/{xblock.location}"
def xblock_type_display_name(xblock, default_display_name=None):
"""
Returns the display name for the specified type of xblock. Note that an instance can be passed in

View File

@@ -2,13 +2,13 @@
Unit tests for helpers.py.
"""
from unittest.mock import patch, Mock
from urllib.parse import quote
from cms.djangoapps.contentstore.tests.utils import CourseTestCase
from xmodule.modulestore.tests.factories import BlockFactory, LibraryFactory # lint-amnesty, pylint: disable=wrong-import-order
from ...helpers import xblock_studio_url, xblock_type_display_name
from ...helpers import xblock_embed_lms_url, xblock_lms_url, xblock_studio_url, xblock_type_display_name
class HelpersTestCase(CourseTestCase):
@@ -60,6 +60,44 @@ class HelpersTestCase(CourseTestCase):
expected_url = f'/library/{str(library.location.library_key)}'
self.assertEqual(xblock_studio_url(library), expected_url)
@patch('cms.djangoapps.contentstore.helpers.configuration_helpers.get_value')
def test_xblock_lms_url(self, mock_get_value: Mock):
mock_get_value.return_value = 'lms.example.com'
# Verify chapter URL
chapter = BlockFactory.create(
parent_location=self.course.location, category='chapter', display_name="Week 1"
)
self.assertEqual(
xblock_lms_url(chapter),
f"lms.example.com/courses/{chapter.location.course_key}/jump_to/{chapter.location}"
)
# Verify sequential URL
sequential = BlockFactory.create(
parent_location=chapter.location, category='sequential', display_name="Lesson 1"
)
self.assertEqual(
xblock_lms_url(sequential),
f"lms.example.com/courses/{sequential.location.course_key}/jump_to/{sequential.location}"
)
@patch('cms.djangoapps.contentstore.helpers.configuration_helpers.get_value')
def test_xblock_embed_lms_url(self, mock_get_value: Mock):
mock_get_value.return_value = 'lms.example.com'
# Verify chapter URL
chapter = BlockFactory.create(
parent_location=self.course.location, category='chapter', display_name="Week 1"
)
self.assertEqual(xblock_embed_lms_url(chapter), f"lms.example.com/xblock/{chapter.location}")
# Verify sequential URL
sequential = BlockFactory.create(
parent_location=chapter.location, category='sequential', display_name="Lesson 1"
)
self.assertEqual(xblock_embed_lms_url(sequential), f"lms.example.com/xblock/{sequential.location}")
def test_xblock_type_display_name(self):
# Verify chapter type display name

View File

@@ -78,6 +78,8 @@ from ..helpers import (
get_parent_xblock,
import_staged_content_from_user_clipboard,
is_unit,
xblock_embed_lms_url,
xblock_lms_url,
xblock_primary_child_category,
xblock_studio_url,
xblock_type_display_name,
@@ -1070,6 +1072,8 @@ def create_xblock_info( # lint-amnesty, pylint: disable=too-many-statements
"published": published,
"published_on": published_on,
"studio_url": xblock_studio_url(xblock, parent_xblock),
"lms_url": xblock_lms_url(xblock),
"embed_lms_url": xblock_embed_lms_url(xblock),
"released_to_students": datetime.now(UTC) > xblock.start,
"release_date": release_date,
"visibility_state": visibility_state,