Files
edx-platform/lms/djangoapps/courseware/plugins.py
Kshitij Sobti d2c2fcdefe feat: Course Apps API [BD-38] [TNL-8103] [BB-2716] (#27542)
* feat: Course Apps API

This adds a new concept called course apps. These are exposed via a new
"openedx.course_app" entrypoint, which helps the LMS and studio discover such
apps and list them in a new rest api for the same.

These course apps will drive the pages and resources view in the course authoring
MFE. This system will track which apps are enabled and which are disabled. It
also allows third-party apps to be listed here by using the plugin entrypoint.

* Apply feedback from review
2021-06-23 21:51:12 +05:00

150 lines
4.6 KiB
Python

"""Course app config for courseware apps."""
from typing import Dict, Optional
from django.conf import settings
from django.contrib.auth import get_user_model
from django.utils.translation import ugettext_noop as _
from opaque_keys.edx.keys import CourseKey
from xmodule.modulestore.django import modulestore
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.course_apps.plugins import CourseApp
from openedx.core.lib.courses import get_course_by_id
User = get_user_model()
TEXTBOOK_ENABLED = settings.FEATURES.get("ENABLE_TEXTBOOK", False)
class ProgressCourseApp(CourseApp):
"""
Course app config for progress app.
"""
app_id = "progress"
name = _("Progress")
description = _("Allow students to track their progress throughout the course.")
@classmethod
def is_available(cls, course_key: CourseKey) -> bool:
"""
The progress course app is always available.
"""
return True
@classmethod
def is_enabled(cls, course_key: CourseKey) -> bool:
"""
The progress course status is stored in the course module.
"""
return not CourseOverview.get_from_id(course_key).hide_progress_tab
@classmethod
def set_enabled(cls, course_key: CourseKey, enabled: bool, user: 'User') -> bool:
"""
The progress course enabled/disabled status is stored in the course module.
"""
course = get_course_by_id(course_key)
course.hide_progress_tab = not enabled
modulestore().update_item(course, user.id)
return enabled
@classmethod
def get_allowed_operations(cls, course_key: CourseKey, user: Optional[User] = None) -> Dict[str, bool]:
"""
Returns the allowed operations for the app.
"""
return {
"enable": True,
"configure": True,
}
class TextbooksCourseApp(CourseApp):
"""
Course app config for textbooks app.
"""
app_id = "textbooks"
name = _("Textbooks")
description = _("Provide links to applicable resources for your course.")
@classmethod
def is_available(cls, course_key: CourseKey) -> bool: # pylint: disable=unused-argument
"""
The textbook app can be made available globally using a value in features.
"""
return TEXTBOOK_ENABLED
@classmethod
def is_enabled(cls, course_key: CourseKey) -> bool: # pylint: disable=unused-argument
"""
Returns if the textbook app is globally enabled.
"""
return TEXTBOOK_ENABLED
@classmethod
def set_enabled(cls, course_key: CourseKey, enabled: bool, user: 'User') -> bool:
"""
The textbook app can be globally enabled/disabled.
Currently, it isn't possible to enable/disable this app on a per-course basis.
"""
raise ValueError("The textbook app can not be enabled/disabled for a single course.")
@classmethod
def get_allowed_operations(cls, course_key: CourseKey, user: Optional[User] = None) -> Dict[str, bool]:
"""
Returns the allowed operations for the app.
"""
return {
# Either the app is available and configurable or not. You cannot disable it from the API yet.
"enable": False,
"configure": True,
}
class CalculatorCourseApp(CourseApp):
"""
Course App config for calculator app.
"""
app_id = "calculator"
name = _("Calculator")
description = _("Provide an in-browser calculator that supports simple and complex calculations.")
@classmethod
def is_available(cls, course_key: CourseKey) -> bool:
"""
Calculator is available for all courses.
"""
return True
@classmethod
def is_enabled(cls, course_key: CourseKey) -> bool:
"""
Get calculator enabled status from course overview model.
"""
return CourseOverview.get_from_id(course_key).show_calculator
@classmethod
def set_enabled(cls, course_key: CourseKey, enabled: bool, user: 'User') -> bool:
"""
Update calculator enabled status in modulestore.
"""
course = get_course_by_id(course_key)
course.show_calculator = enabled
modulestore().update_item(course, user.id)
return enabled
@classmethod
def get_allowed_operations(cls, course_key: CourseKey, user: Optional[User] = None) -> Dict[str, bool]:
"""
Get allowed operations for calculator app.
"""
return {
"enable": True,
# There is nothing to configure for calculator yet.
"configure": False,
}