Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collections Django Admin + soft delete, hard delete, and restore #229

Merged
merged 6 commits into from
Sep 24, 2024
Merged
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 Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ upgrade: ## update the pip requirements files to use the latest releases satisf

quality: ## check coding style with pycodestyle and pylint
tox -e quality
lint-imports

pii_check: ## check for PII annotations on all Django models
tox -e pii_check
Expand Down
2 changes: 1 addition & 1 deletion openedx_learning/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""
Open edX Learning ("Learning Core").
"""
__version__ = "0.12.0"
__version__ = "0.13.0"
27 changes: 27 additions & 0 deletions openedx_learning/apps/authoring/collections/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
Django Admin pages for Collection models.
"""
from django.contrib import admin

from .models import Collection


class CollectionAdmin(admin.ModelAdmin):
"""
The Collection model admin.

Allows users to easily disable/enable (aka soft delete and restore) or bulk delete Collections.
"""
readonly_fields = ["key", "learning_package"]
list_filter = ["enabled"]
list_display = ["key", "title", "enabled", "modified"]
list_editable = ["enabled"]

def has_add_permission(self, request, *args, **kwargs):
"""
Disallow adding new collections via Django Admin.
"""
return False # pragma: no cover


admin.site.register(Collection, CollectionAdmin)
38 changes: 38 additions & 0 deletions openedx_learning/apps/authoring/collections/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
__all__ = [
"add_to_collection",
"create_collection",
"delete_collection",
"get_collection",
"get_collections",
"get_entity_collections",
"remove_from_collection",
"restore_collection",
"update_collection",
]

Expand Down Expand Up @@ -84,6 +86,42 @@ def update_collection(
return collection


def delete_collection(
learning_package_id: int,
key: str,
*,
hard_delete=False,
) -> Collection:
"""
Disables or deletes a collection identified by the given learning_package + key.

By default (hard_delete=False), the collection is "soft deleted", i.e disabled.
Soft-deleted collections can be re-enabled using restore_collection.
"""
collection = get_collection(learning_package_id, key)

if hard_delete:
collection.delete()
else:
collection.enabled = False
collection.save()
return collection


def restore_collection(
learning_package_id: int,
key: str,
) -> Collection:
"""
Undo a "soft delete" by re-enabling a Collection.
"""
collection = get_collection(learning_package_id, key)

collection.enabled = True
collection.save()
return collection


def add_to_collection(
learning_package_id: int,
key: str,
Expand Down
16 changes: 16 additions & 0 deletions openedx_learning/apps/authoring/components/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"get_component_by_uuid",
"get_component_version_by_uuid",
"component_exists_by_key",
"get_collection_components",
"get_components",
"create_component_version_content",
"look_up_component_version_content",
Expand Down Expand Up @@ -339,6 +340,21 @@ def get_components(
return qset


def get_collection_components(
learning_package_id: int,
collection_key: str,
) -> QuerySet[Component]:
"""
Returns a QuerySet of Components relating to the PublishableEntities in a Collection.

Components have a one-to-one relationship with PublishableEntity, but the reverse may not always be true.
"""
return Component.objects.filter(
learning_package_id=learning_package_id,
publishable_entity__collections__key=collection_key,
).order_by('pk')


def look_up_component_version_content(
learning_package_key: str,
component_key: str,
Expand Down
Loading