Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
17 changes: 15 additions & 2 deletions openedx_learning/apps/authoring/components/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,20 @@ def create_component(
local_key: str,
created: datetime,
created_by: int | None,
*,
can_stand_alone: bool = True,
) -> Component:
"""
Create a new Component (an entity like a Problem or Video)
"""
key = f"{component_type.namespace}:{component_type.name}:{local_key}"
with atomic():
publishable_entity = publishing_api.create_publishable_entity(
learning_package_id, key, created, created_by
learning_package_id,
key,
created,
created_by,
can_stand_alone=can_stand_alone
)
component = Component.objects.create(
publishable_entity=publishable_entity,
Expand Down Expand Up @@ -239,13 +245,20 @@ def create_component_and_version( # pylint: disable=too-many-positional-argumen
title: str,
created: datetime,
created_by: int | None = None,
*,
can_stand_alone: bool = True,
) -> tuple[Component, ComponentVersion]:
"""
Create a Component and associated ComponentVersion atomically
"""
with atomic():
component = create_component(
learning_package_id, component_type, local_key, created, created_by
learning_package_id,
component_type,
local_key,
created,
created_by,
can_stand_alone=can_stand_alone,
)
component_version = create_component_version(
component.pk,
Expand Down
3 changes: 3 additions & 0 deletions openedx_learning/apps/authoring/publishing/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class PublishableEntityAdmin(ReadOnlyModelAdmin):
"learning_package",
"created",
"created_by",
"can_stand_alone",
]
list_filter = ["learning_package"]
search_fields = ["key", "uuid"]
Expand All @@ -98,6 +99,7 @@ class PublishableEntityAdmin(ReadOnlyModelAdmin):
"created",
"created_by",
"see_also",
"can_stand_alone",
]
readonly_fields = [
"key",
Expand All @@ -108,6 +110,7 @@ class PublishableEntityAdmin(ReadOnlyModelAdmin):
"created",
"created_by",
"see_also",
"can_stand_alone",
]

def get_queryset(self, request):
Expand Down
11 changes: 10 additions & 1 deletion openedx_learning/apps/authoring/publishing/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ def create_publishable_entity(
created: datetime,
# User ID who created this
created_by: int | None,
*,
can_stand_alone: bool = True,
) -> PublishableEntity:
"""
Create a PublishableEntity.
Expand All @@ -185,6 +187,7 @@ def create_publishable_entity(
key=key,
created=created,
created_by_id=created_by,
can_stand_alone=can_stand_alone,
)


Expand Down Expand Up @@ -583,6 +586,8 @@ def create_container(
key: str,
created: datetime,
created_by: int | None,
*,
can_stand_alone: bool = True,
# The types on the following line are correct, but mypy will complain - https://github.com/python/mypy/issues/3737
container_cls: type[ContainerModel] = Container, # type: ignore[assignment]
) -> ContainerModel:
Expand All @@ -603,7 +608,11 @@ def create_container(
assert issubclass(container_cls, Container)
with atomic():
publishable_entity = create_publishable_entity(
learning_package_id, key, created, created_by
learning_package_id,
key,
created,
created_by,
can_stand_alone=can_stand_alone,
)
container = container_cls.objects.create(
publishable_entity=publishable_entity,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.19 on 2025-03-17 11:07

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('oel_publishing', '0003_containers'),
]

operations = [
migrations.AddField(
model_name='publishableentity',
name='can_stand_alone',
field=models.BooleanField(default=True),
),
]
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class PublishableEntity(models.Model):
null=True,
blank=True,
)
can_stand_alone = models.BooleanField(default=True)
Copy link
Contributor

Choose a reason for hiding this comment

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

@navinkarkera I think we need to add a comment to explain this field. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes please -- could you put it in the field help_text so it's visible in Django Admin too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


class Meta:
constraints = [
Expand Down
17 changes: 15 additions & 2 deletions openedx_learning/apps/authoring/units/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@


def create_unit(
learning_package_id: int, key: str, created: datetime, created_by: int | None
learning_package_id: int,
key: str,
created: datetime,
created_by: int | None,
*,
can_stand_alone: bool = True,
) -> Unit:
"""
[ 🛑 UNSTABLE ] Create a new unit.
Expand All @@ -46,6 +51,7 @@ def create_unit(
key,
created,
created_by,
can_stand_alone=can_stand_alone,
container_cls=Unit,
)

Expand Down Expand Up @@ -156,6 +162,7 @@ def create_unit_and_version(
components: list[Component | ComponentVersion] | None = None,
created: datetime,
created_by: int | None = None,
can_stand_alone: bool = True,
) -> tuple[Unit, UnitVersion]:
"""
[ 🛑 UNSTABLE ] Create a new unit and its version.
Expand All @@ -168,7 +175,13 @@ def create_unit_and_version(
"""
publishable_entities_pks, entity_version_pks = _pub_entities_for_components(components)
with atomic():
unit = create_unit(learning_package_id, key, created, created_by)
unit = create_unit(
learning_package_id,
key,
created,
created_by,
can_stand_alone=can_stand_alone,
)
unit_version = create_unit_version(
unit,
1,
Expand Down
11 changes: 11 additions & 0 deletions tests/openedx_learning/apps/authoring/components/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ def setUpTestData(cls) -> None:
local_key='my_component',
created=cls.now,
created_by=None,
can_stand_alone=False,
)

def test_simple_get(self):
Expand All @@ -333,6 +334,16 @@ def test_publishing_entity_key_convention(self):
"""Our mapping convention is {namespace}:{component_type}:{local_key}"""
assert self.problem.key == "xblock.v1:problem:my_component"

def test_stand_alone_flag(self):
"""Check if can_stand_alone flag is set"""
component = components_api.get_component_by_key(
self.learning_package.id,
namespace='xblock.v1',
type_name='html',
local_key='my_component',
)
assert not component.publishable_entity.can_stand_alone

def test_get_by_key(self):
assert self.html == components_api.get_component_by_key(
self.learning_package.id,
Expand Down
1 change: 1 addition & 0 deletions tests/openedx_learning/apps/authoring/units/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ def test_create_empty_unit_and_version(self):
assert unit.versioning.has_unpublished_changes
assert unit.versioning.draft == unit_version
assert unit.versioning.published is None
assert unit.publishable_entity.can_stand_alone

def test_create_next_unit_version_with_two_unpinned_components(self):
"""Test creating a unit version with two unpinned components.
Expand Down