Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
name: ${{ matrix.shard_name }}(py=${{ matrix.python-version }},dj=${{ matrix.django-version }},mongo=${{ matrix.mongo-version }})
runs-on: ${{ matrix.os-version }}
strategy:
fail-fast: false
matrix:
python-version:
- "3.11"
Expand Down
1 change: 1 addition & 0 deletions cms/djangoapps/contentstore/views/preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from xmodule.util.builtin_assets import add_webpack_js_to_fragment
from xmodule.x_module import AUTHOR_VIEW, PREVIEW_VIEWS, STUDENT_VIEW, XModuleMixin
from cms.djangoapps.xblock_config.models import StudioConfig
from openedx.core.djangoapps.video_config.services import VideoConfigService
from cms.djangoapps.contentstore.toggles import individualize_anonymous_user_id
from cms.lib.xblock.field_data import CmsFieldData
from cms.lib.xblock.upstream_sync import UpstreamLink
Expand Down
2 changes: 1 addition & 1 deletion cms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@
'statici18n',

# Tagging
'cms.lib.xblock.tagging',
'cms.lib.xblock.tagging.apps.TaggingConfig',

# Enables default site and redirects
'django_sites_extensions',
Expand Down
12 changes: 12 additions & 0 deletions cms/lib/xblock/tagging/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What makes this change necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These logs pushed me to do this change.

Logs are taken from e33585a commit test run.

Issue fixed by creating the AppConfig class for tagging app.

Django app configuration for the XBlock tagging app
"""
from django.apps import AppConfig


class TaggingConfig(AppConfig):
"""
Django app configuration for the XBlock tagging app
"""
name = 'cms.lib.xblock.tagging'
verbose_name = 'XBlock Tagging'
1 change: 1 addition & 0 deletions lms/djangoapps/courseware/block_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from lms.djangoapps.teams.services import TeamsService
from openedx.core.djangoapps.video_config.services import VideoConfigService
from openedx.core.lib.xblock_services.call_to_action import CallToActionService
from openedx.core.djangoapps.video_config.services import VideoConfigService
from xmodule.contentstore.django import contentstore
from xmodule.exceptions import NotFoundError, ProcessingError
from xmodule.library_tools import LegacyLibraryToolsService
Expand Down
87 changes: 87 additions & 0 deletions openedx/core/djangoapps/video_config/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
from openedx.core.djangoapps.video_config.toggles import TRANSCRIPT_FEEDBACK
from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE

from xmodule.contentstore.content import StaticContent
from xmodule.contentstore.django import contentstore
from xmodule.exceptions import NotFoundError

log = logging.getLogger(__name__)


Expand Down Expand Up @@ -120,3 +124,86 @@ def get_transcript(
raise TranscriptNotFoundError(
f"Failed to get transcript: {exc}"
) from exc

def get_transcript_from_store(self, course_key, filename):
"""
Return transcript from static content store by course key and filename.

Args:
course_key: Course key
filename (str): filename of the asset

Returns:
transcript from store

Raises:
TranscriptNotFoundError: If transcript not found
"""
content_location = StaticContent.compute_location(course_key, filename)
try:
return contentstore().find(content_location)
except NotFoundError as exc:
raise TranscriptNotFoundError(
f"Failed to get transcript: {exc}"
) from exc

def delete_transcript_from_store(self, course_key, filename):
"""
Delete transcript from store by course key and filename.

Args:
course_key: Course key
filename (str): filename of the asset

Returns:
Asset location
"""
try:
content_location = StaticContent.compute_location(course_key, filename)
contentstore().delete(content_location)
log.info("Transcript asset %s was removed from store.", filename)
except NotFoundError as exc:
raise TranscriptNotFoundError(
f"Failed to get transcript: {exc}"
) from exc
return StaticContent.compute_location(course_key, filename)

def find_transcript_from_store(self, course_key, filename):
"""
Find transcript from store by course key and filename.

Args:
course_key: Course key
filename (str): filename of the asset

Returns:
transcript from store

Raises:
TranscriptNotFoundError: If transcript not found
"""
try:
content_location = StaticContent.compute_location(course_key, filename)
return contentstore().find(content_location).data.decode('utf-8')
except NotFoundError as exc:
raise TranscriptNotFoundError(
f"Failed to get transcript: {exc}"
) from exc

def save_transcript_into_store(self, content, filename, mime_type, course_key):
"""
Save transcript into store by course key.

Args:
content: The content to save
filename: The filename
mime_type: The MIME type of the content
course_key: The course key

Returns:
Content location of saved transcript in store
"""
content_location = StaticContent.compute_location(course_key, filename)
content = StaticContent(content_location, filename, mime_type, content)
contentstore().save(content)
return content_location
41 changes: 40 additions & 1 deletion openedx/core/djangoapps/video_config/transcripts_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
from pysrt.srtexc import Error
from opaque_keys.edx.locator import LibraryLocatorV2

from openedx.core.djangoapps.xblock.api import get_component_from_usage_key
from xmodule.contentstore.content import StaticContent
from xmodule.contentstore.django import contentstore
from xmodule.exceptions import NotFoundError
Expand Down Expand Up @@ -796,6 +795,14 @@ def get_asset(location, filename):
"""
return contentstore().find(Transcript.asset_location(location, filename))

@staticmethod
def get_asset_by_course_key(course_key, filename):
"""
Return asset by location and filename.
"""
content_location = StaticContent.compute_location(course_key, filename)
return contentstore().find(content_location)

@staticmethod
def asset_location(location, filename):
"""
Expand All @@ -818,6 +825,37 @@ def delete_asset(location, filename):
pass
return StaticContent.compute_location(location.course_key, filename)

@staticmethod
def delete_asset_by_course_key(course_key, filename):
"""
Delete asset by location and filename.
"""
try:
content_location = StaticContent.compute_location(course_key, filename)
contentstore().delete(content_location)
log.info("Transcript asset %s was removed from store.", filename)
except NotFoundError:
pass
return StaticContent.compute_location(course_key, filename)

@staticmethod
def find_asset(course_key, filename):
"""
Finds asset by course_key and filename.
"""
content_location = StaticContent.compute_location(course_key, filename)
return contentstore().find(content_location).data.decode('utf-8')

@staticmethod
def save_transcript(content, filename, mime_type, course_key):
"""
Save transcript to store by course_key and filename.
"""
content_location = StaticContent.compute_location(course_key, filename)
content = StaticContent(content_location, filename, mime_type, content)
contentstore().save(content)
return content_location


class VideoTranscriptsMixin:
"""Mixin class for transcript functionality.
Expand Down Expand Up @@ -1117,6 +1155,7 @@ def get_transcript_from_learning_core(video_block, language, output_format, tran
# Grab the underlying Component. There's no version parameter to this call,
# so we're just going to grab the file associated with the latest draft
# version for now.
from openedx.core.djangoapps.xblock.api import get_component_from_usage_key
component = get_component_from_usage_key(usage_key)
component_version = component.versioning.draft
if not component_version:
Expand Down
96 changes: 96 additions & 0 deletions openedx/core/djangoapps/video_config/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"""
Video configuration utilities
"""

import logging

from django.conf import settings

from openedx.core.djangoapps.video_config.toggles import PUBLIC_VIDEO_SHARE
from openedx.core.lib.courses import get_course_by_id
from xmodule.course_block import (
COURSE_VIDEO_SHARING_ALL_VIDEOS,
COURSE_VIDEO_SHARING_NONE,
)

log = logging.getLogger(__name__)


class VideoSharingUtils:
"""
Provides utility methods for video sharing functionality.
"""

@staticmethod
def get_public_video_url(video_block):
"""
Returns the public video url for a video block.

Args:
video_block: The video XBlock instance

Returns:
str: The public video URL
"""
return fr'{settings.LMS_ROOT_URL}/videos/{str(video_block.location)}'

@staticmethod
def is_public_sharing_enabled(video_block):
"""
Check if public sharing is enabled for a video.

Args:
video_block: The video XBlock instance

Returns:
bool: True if public sharing is enabled, False otherwise
"""
if not video_block.context_key.is_course:
return False # Only courses support this feature (not libraries)

try:
# Video share feature must be enabled for sharing settings to take effect
feature_enabled = PUBLIC_VIDEO_SHARE.is_enabled(video_block.context_key)
except Exception as err: # pylint: disable=broad-except
log.exception(f"Error retrieving course for course ID: {video_block.context_key}")
return False

if not feature_enabled:
return False

# Check if the course specifies a general setting
course_video_sharing_option = VideoSharingUtils.get_course_video_sharing_override(video_block)

# Course can override all videos to be shared
if course_video_sharing_option == COURSE_VIDEO_SHARING_ALL_VIDEOS:
return True

# ... or no videos to be shared
elif course_video_sharing_option == COURSE_VIDEO_SHARING_NONE:
return False

# ... or can fall back to per-video setting
# Equivalent to COURSE_VIDEO_SHARING_PER_VIDEO or None / unset
else:
return video_block.public_access

@staticmethod
def get_course_video_sharing_override(video_block):
"""
Return course video sharing options override or None

Args:
video_block: The video XBlock instance

Returns:
Course video sharing option or None
"""
if not video_block.context_key.is_course:
return False # Only courses support this feature (not libraries)

try:
course = get_course_by_id(video_block.context_key)
return getattr(course, 'video_sharing_options', None)
except Exception as err: # pylint: disable=broad-except
log.exception(f"Error retrieving course for course ID: {video_block.course_id}")
return None
2 changes: 1 addition & 1 deletion openedx/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1736,7 +1736,7 @@ def _make_locale_paths(settings):
# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done.
# .. toggle_creation_date: 2024-11-10
# .. toggle_target_removal_date: 2025-06-01
USE_EXTRACTED_VIDEO_BLOCK = False
USE_EXTRACTED_VIDEO_BLOCK = True

############################## Marketing Site ##############################

Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1279,7 +1279,7 @@ xblock-utils==4.0.0
# via
# edx-sga
# xblock-poll
xblocks-contrib==0.8.1
git+https://github.com/openedx/xblocks-contrib.git@farhan/video-xblock-extraction
# via -r requirements/edx/bundled.in
xmlsec==1.3.14
# via
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/development.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2312,7 +2312,7 @@ xblock-utils==4.0.0
# -r requirements/edx/testing.txt
# edx-sga
# xblock-poll
xblocks-contrib==0.8.1
git+https://github.com/openedx/xblocks-contrib.git@farhan/video-xblock-extraction
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1617,7 +1617,7 @@ xblock-utils==4.0.0
# -r requirements/edx/base.txt
# edx-sga
# xblock-poll
xblocks-contrib==0.8.1
git+https://github.com/openedx/xblocks-contrib.git@farhan/video-xblock-extraction
# via -r requirements/edx/base.txt
xmlsec==1.3.14
# via
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1710,7 +1710,7 @@ xblock-utils==4.0.0
# -r requirements/edx/base.txt
# edx-sga
# xblock-poll
xblocks-contrib==0.8.1
git+https://github.com/openedx/xblocks-contrib.git@farhan/video-xblock-extraction
# via -r requirements/edx/base.txt
xmlsec==1.3.14
# via
Expand Down
Loading