feat: New fields in library v2 details API view (#35091)
This commit is contained in:
@@ -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
|
||||
@@ -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:
|
||||
@@ -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
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
@@ -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").
|
||||
"""
|
||||
@@ -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(
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
@@ -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(
|
||||
|
||||
@@ -36,12 +36,14 @@ 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)
|
||||
@@ -49,6 +51,8 @@ class ContentLibraryMetadataSerializer(serializers.Serializer):
|
||||
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):
|
||||
"""
|
||||
|
||||
@@ -487,7 +487,7 @@ class LibraryCommitView(APIView):
|
||||
"""
|
||||
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
|
||||
@@ -556,7 +556,7 @@ class LibraryBlocksView(GenericAPIView):
|
||||
|
||||
# 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)},
|
||||
|
||||
Reference in New Issue
Block a user