Skip to content

Commit

Permalink
feat: Add REST-API to create a collection
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisChV committed Sep 7, 2024
1 parent 135a7ca commit 590fc0e
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 0 deletions.
2 changes: 2 additions & 0 deletions openedx/core/djangoapps/content_libraries/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class ContentLibraryMetadata:
key = attr.ib(type=LibraryLocatorV2)
title = attr.ib("")
description = attr.ib("")
learning_package_id = attr.ib(default=None, type=int)
num_blocks = attr.ib(0)
version = attr.ib(0)
type = attr.ib(default=COMPLEX)
Expand Down Expand Up @@ -392,6 +393,7 @@ def get_library(library_key):
return ContentLibraryMetadata(
key=library_key,
title=learning_package.title,
learning_package_id = learning_package.id,
type=ref.type,
description=ref.learning_package.description,
num_blocks=num_blocks,
Expand Down
20 changes: 20 additions & 0 deletions openedx/core/djangoapps/content_libraries/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,23 @@ class ContentLibraryBlockImportTaskCreateSerializer(serializers.Serializer):
"""

course_key = CourseKeyField()


class LibraryCollectionCreationSerializer(serializers.Serializer):
"""
Serializer to create a new library collection.
"""

title = serializers.CharField()
description = serializers.CharField()

class LibraryCollectionMetadataSerializer(serializers.Serializer):
"""
Serializer for Library Collection Metadata.
"""

id = serializers.CharField(read_only=True)
# Rename collection.key to "slug" because "key" is a reserved prop name in React
slug = serializers.CharField(read_only=True)
title = serializers.CharField()
description = serializers.CharField(allow_blank=True)
2 changes: 2 additions & 0 deletions openedx/core/djangoapps/content_libraries/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
path('import_blocks/', include(import_blocks_router.urls)),
# Paste contents of clipboard into library
path('paste_clipboard/', views.LibraryPasteClipboardView.as_view()),
# list of library collections / create a library collection
path('collections/', views.LibraryCollectionsRootView.as_view()),
])),
path('blocks/<str:usage_key_str>/', include([
# Get metadata about a specific XBlock in this library, or delete the block:
Expand Down
47 changes: 47 additions & 0 deletions openedx/core/djangoapps/content_libraries/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.decorators.csrf import csrf_exempt
from django.views.generic.base import TemplateResponseMixin, View
from django.utils.text import slugify
from pylti1p3.contrib.django import DjangoCacheDataStorage, DjangoDbToolConf, DjangoMessageLaunch, DjangoOIDCLogin
from pylti1p3.exception import LtiException, OIDCException

Expand All @@ -88,6 +89,7 @@
from organizations.api import ensure_organization
from organizations.exceptions import InvalidOrganizationException
from organizations.models import Organization
from openedx_learning.api import authoring as authoring_api
from rest_framework import status
from rest_framework.exceptions import NotFound, PermissionDenied, ValidationError
from rest_framework.generics import GenericAPIView
Expand All @@ -113,6 +115,8 @@
LibraryXBlockStaticFilesSerializer,
ContentLibraryAddPermissionByEmailSerializer,
LibraryPasteClipboardSerializer,
LibraryCollectionCreationSerializer,
LibraryCollectionMetadataSerializer,
)
import openedx.core.djangoapps.site_configuration.helpers as configuration_helpers
from openedx.core.lib.api.view_utils import view_auth_classes
Expand Down Expand Up @@ -154,6 +158,10 @@ def wrapped_fn(*args, **kwargs):
return wrapped_fn


# Library 1.3 Views
# =============


class LibraryApiPaginationDocs:
"""
API docs for query params related to paginating ContentLibraryMetadata objects.
Expand Down Expand Up @@ -829,6 +837,45 @@ def retrieve(self, request, lib_key_str, pk=None):
return Response(ContentLibraryBlockImportTaskSerializer(import_task).data)


# Library Collections Views
# =============

@method_decorator(non_atomic_requests, name="dispatch")
@view_auth_classes()
class LibraryCollectionsRootView(GenericAPIView):
"""
Views to list and create library collections.
"""

# TODO Implement list collections

def post(self, request, lib_key_str):
"""
Create a new collection library.
"""
library_key = LibraryLocatorV2.from_string(lib_key_str)
api.require_permission_for_library_key(library_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
serializer = LibraryCollectionCreationSerializer(data=request.data)
serializer.is_valid(raise_exception=True)

library = api.get_library(library_key)
title = serializer.validated_data['title']

key = slugify(title)

# TODO verify if key is unique

result = authoring_api.create_collection(
learning_package_id=library.learning_package_id,
key=key,
title=title,
description=serializer.validated_data['description'],
created_by=request.user.id,
)

return Response(LibraryCollectionMetadataSerializer(result).data)


# LTI 1.3 Views
# =============

Expand Down

0 comments on commit 590fc0e

Please sign in to comment.