Skip to content

Commit

Permalink
feat: New fields in library v2 details API view (#35091)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisChV authored Aug 1, 2024
1 parent a7f6cf1 commit 2788f2b
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 11 deletions.
32 changes: 24 additions & 8 deletions openedx/core/djangoapps/content_libraries/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ class ContentLibraryMetadata:
version = attr.ib(0)
type = attr.ib(default=COMPLEX)
last_published = attr.ib(default=None, type=datetime)
last_draft_created = attr.ib(default=None, type=datetime)
last_draft_created_by = attr.ib(default=None, type=datetime)
published_by = attr.ib("")
has_unpublished_changes = attr.ib(False)
# has_unpublished_deletes will be true when the draft version of the library's bundle
# contains deletes of any XBlocks that were in the most recently published version
Expand All @@ -168,6 +171,8 @@ class ContentLibraryMetadata:
# Studio, use it in their courses, and copy content out of this library.
allow_public_read = attr.ib(False)
license = attr.ib("")
created = attr.ib(default=None, type=datetime)
updated = attr.ib(default=None, type=datetime)


class AccessLevel:
Expand Down Expand Up @@ -350,8 +355,11 @@ def get_library(library_key):
learning_package = ref.learning_package
num_blocks = authoring_api.get_all_drafts(learning_package.id).count()
last_publish_log = authoring_api.get_last_publish(learning_package.id)
has_unpublished_changes = authoring_api.get_entities_with_unpublished_changes(learning_package.id) \
.exists()
last_draft_log = authoring_api.get_entities_with_unpublished_changes(learning_package.id) \
.order_by('-created').first()
last_draft_created = last_draft_log.created if last_draft_log else None
last_draft_created_by = last_draft_log.created_by.username if last_draft_log and last_draft_log.created_by else None
has_unpublished_changes = last_draft_log is not None

# TODO: I'm doing this one to match already-existing behavior, but this is
# something that we should remove. It exists to accomodate some complexities
Expand All @@ -377,6 +385,9 @@ def get_library(library_key):
# libraries. The top level version stays for now because LibraryContentBlock
# uses it, but that should hopefully change before the Redwood release.
version = 0 if last_publish_log is None else last_publish_log.pk
published_by = None
if last_publish_log and last_publish_log.published_by:
published_by = last_publish_log.published_by.username

return ContentLibraryMetadata(
key=library_key,
Expand All @@ -386,12 +397,17 @@ def get_library(library_key):
num_blocks=num_blocks,
version=version,
last_published=None if last_publish_log is None else last_publish_log.published_at,
published_by=published_by,
last_draft_created=last_draft_created,
last_draft_created_by=last_draft_created_by,
allow_lti=ref.allow_lti,
allow_public_learning=ref.allow_public_learning,
allow_public_read=ref.allow_public_read,
has_unpublished_changes=has_unpublished_changes,
has_unpublished_deletes=has_unpublished_deletes,
license=ref.license,
created=learning_package.created,
updated=learning_package.updated,
)


Expand Down Expand Up @@ -735,7 +751,7 @@ def set_library_block_olx(usage_key, new_olx_str):
)


def create_library_block(library_key, block_type, definition_id):
def create_library_block(library_key, block_type, definition_id, user_id=None):
"""
Create a new XBlock in this library of the specified type (e.g. "html").
"""
Expand Down Expand Up @@ -777,7 +793,7 @@ def create_library_block(library_key, block_type, definition_id):
if _component_exists(usage_key):
raise LibraryBlockAlreadyExists(f"An XBlock with ID '{usage_key}' already exists")

_create_component_for_block(ref, usage_key)
_create_component_for_block(ref, usage_key, user_id=user_id)

# Now return the metadata about the new block:
LIBRARY_BLOCK_CREATED.send_event(
Expand Down Expand Up @@ -816,7 +832,7 @@ def get_or_create_olx_media_type(block_type: str) -> MediaType:
)


def _create_component_for_block(content_lib, usage_key):
def _create_component_for_block(content_lib, usage_key, user_id=None):
"""
Create a Component for an XBlock type, and initialize it.
Expand Down Expand Up @@ -847,7 +863,7 @@ def _create_component_for_block(content_lib, usage_key):
local_key=usage_key.block_id,
title=display_name,
created=now,
created_by=None,
created_by=user_id,
)
content = authoring_api.get_or_create_text_content(
learning_package.id,
Expand Down Expand Up @@ -951,13 +967,13 @@ def get_allowed_block_types(library_key): # pylint: disable=unused-argument
return info


def publish_changes(library_key):
def publish_changes(library_key, user_id=None):
"""
Publish all pending changes to the specified library.
"""
learning_package = ContentLibrary.objects.get_by_key(library_key).learning_package

authoring_api.publish_all_drafts(learning_package.id)
authoring_api.publish_all_drafts(learning_package.id, published_by=user_id)

CONTENT_LIBRARY_UPDATED.send_event(
content_library=ContentLibraryData(
Expand Down
6 changes: 5 additions & 1 deletion openedx/core/djangoapps/content_libraries/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,23 @@ class ContentLibraryMetadataSerializer(serializers.Serializer):
org = serializers.SlugField(source="key.org")
slug = serializers.CharField(source="key.slug", validators=(validate_unicode_slug, ))
bundle_uuid = serializers.UUIDField(format='hex_verbose', read_only=True)
#collection_uuid = serializers.UUIDField(format='hex_verbose', write_only=True)
title = serializers.CharField()
description = serializers.CharField(allow_blank=True)
num_blocks = serializers.IntegerField(read_only=True)
version = serializers.IntegerField(read_only=True)
last_published = serializers.DateTimeField(format=DATETIME_FORMAT, read_only=True)
published_by = serializers.CharField(read_only=True)
last_draft_created = serializers.DateTimeField(format=DATETIME_FORMAT, read_only=True)
last_draft_created_by = serializers.CharField(read_only=True)
allow_lti = serializers.BooleanField(default=False, read_only=True)
allow_public_learning = serializers.BooleanField(default=False)
allow_public_read = serializers.BooleanField(default=False)
has_unpublished_changes = serializers.BooleanField(read_only=True)
has_unpublished_deletes = serializers.BooleanField(read_only=True)
license = serializers.ChoiceField(choices=LICENSE_OPTIONS, default=ALL_RIGHTS_RESERVED)
can_edit_library = serializers.SerializerMethodField()
created = serializers.DateTimeField(format=DATETIME_FORMAT, read_only=True)
updated = serializers.DateTimeField(format=DATETIME_FORMAT, read_only=True)

def get_can_edit_library(self, obj):
"""
Expand Down
4 changes: 2 additions & 2 deletions openedx/core/djangoapps/content_libraries/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ def post(self, request, lib_key_str):
"""
key = LibraryLocatorV2.from_string(lib_key_str)
api.require_permission_for_library_key(key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
api.publish_changes(key)
api.publish_changes(key, request.user.id)
return Response({})

@convert_exceptions
Expand Down Expand Up @@ -556,7 +556,7 @@ def post(self, request, lib_key_str):

# Create a new regular top-level block:
try:
result = api.create_library_block(library_key, **serializer.validated_data)
result = api.create_library_block(library_key, user_id=request.user.id, **serializer.validated_data)
except api.IncompatibleTypesError as err:
raise ValidationError( # lint-amnesty, pylint: disable=raise-missing-from
detail={'block_type': str(err)},
Expand Down

0 comments on commit 2788f2b

Please sign in to comment.