This introduces the modulestore_migrator app, which can be used to copy content (courses and libraries) from modulestore into Learning Core. It is currently aimed to work on the legacy library -> v2 library migration, but it will be used in the future for course->library and course->course migrations. This includes an initial REST API, Django admin interface, and Python API. Closes: https://github.com/openedx/edx-platform/issues/37211 Requires some follow-up work before this is production-ready: https://github.com/openedx/edx-platform/issues/37259 Co-authored-by: Andrii <andrii.hantkovskyi@raccoongang.com> Co-authored-by: Maksim Sokolskiy <maksim.sokolskiy@raccoongang.com>
82 lines
2.2 KiB
Python
82 lines
2.2 KiB
Python
"""
|
|
Value objects
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from enum import Enum
|
|
|
|
from openedx.core.djangoapps.content_libraries.api import ContainerType
|
|
|
|
|
|
class CompositionLevel(Enum):
|
|
"""
|
|
Enumeration of composition levels for legacy content.
|
|
|
|
Defined in increasing order of complexity so that `is_higher_than` works correctly.
|
|
"""
|
|
# Components are individual XBlocks, e.g. Problem
|
|
Component = 'component'
|
|
|
|
# Container types currently supported by Content Libraries
|
|
Unit = ContainerType.Unit.value
|
|
Subsection = ContainerType.Subsection.value
|
|
Section = ContainerType.Section.value
|
|
|
|
@property
|
|
def is_container(self) -> bool:
|
|
return self is not self.Component
|
|
|
|
def is_higher_than(self, other: 'CompositionLevel') -> bool:
|
|
"""
|
|
Is this composition level 'above' (more complex than) the other?
|
|
"""
|
|
levels: list[CompositionLevel] = list(self.__class__)
|
|
return levels.index(self) > levels.index(other)
|
|
|
|
@classmethod
|
|
def supported_choices(cls) -> list[tuple[str, str]]:
|
|
"""
|
|
Returns all supported composition levels as a list of tuples,
|
|
for use in a Django Models ChoiceField.
|
|
"""
|
|
return [
|
|
(composition_level.value, composition_level.name)
|
|
for composition_level in cls
|
|
]
|
|
|
|
|
|
class RepeatHandlingStrategy(Enum):
|
|
"""
|
|
Enumeration of repeat handling strategies for imported content.
|
|
"""
|
|
Skip = 'skip'
|
|
Fork = 'fork'
|
|
Update = 'update'
|
|
|
|
@classmethod
|
|
def supported_choices(cls) -> list[tuple[str, str]]:
|
|
"""
|
|
Returns all supported repeat handling strategies as a list of tuples,
|
|
for use in a Django Models ChoiceField.
|
|
"""
|
|
return [
|
|
(strategy.value, strategy.name)
|
|
for strategy in cls
|
|
]
|
|
|
|
@classmethod
|
|
def default(cls) -> RepeatHandlingStrategy:
|
|
"""
|
|
Returns the default repeat handling strategy.
|
|
"""
|
|
return cls.Skip
|
|
|
|
def is_implemented(self) -> bool:
|
|
"""
|
|
Returns True if the repeat handling strategy is implemented.
|
|
"""
|
|
if self == self.Fork:
|
|
raise NotImplementedError("Forking is not implemented yet.")
|
|
|
|
return True
|