From 2842533eb4ff73a7f59a10dea81a8bddf959cceb Mon Sep 17 00:00:00 2001 From: Andy Armstrong Date: Tue, 20 Jun 2017 19:03:37 -0400 Subject: [PATCH] Introduce a course_tool plugin entry point and migrate the updates, bookmarks and reviews tools into plugins. --- openedx/features/course_bookmarks/plugins.py | 40 ++++++++++ .../course_experience/course_tools.py | 67 ++++++++++++++++ openedx/features/course_experience/plugins.py | 79 +++++++++++++++++++ .../course-home-fragment.html | 48 +++++------ setup.py | 13 +-- 5 files changed, 215 insertions(+), 32 deletions(-) create mode 100644 openedx/features/course_bookmarks/plugins.py create mode 100644 openedx/features/course_experience/course_tools.py create mode 100644 openedx/features/course_experience/plugins.py diff --git a/openedx/features/course_bookmarks/plugins.py b/openedx/features/course_bookmarks/plugins.py new file mode 100644 index 0000000000..3f24942ae8 --- /dev/null +++ b/openedx/features/course_bookmarks/plugins.py @@ -0,0 +1,40 @@ +""" +Platform plugins to support course bookmarks. +""" + +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ +from openedx.features.course_experience.course_tools import CourseTool + + +class CourseBookmarksTool(CourseTool): + """ + The course bookmarks tool. + """ + @classmethod + def is_enabled(cls, course_key): + """ + Always show the bookmarks tool. + """ + return True + + @classmethod + def title(cls): + """ + Returns the title of this tool. + """ + return _('Bookmarks') + + @classmethod + def icon_classes(cls): + """ + Returns the icon classes needed to represent this tool. + """ + return 'fa fa-bookmark' + + @classmethod + def url(cls, course_key): + """ + Returns the URL for this tool for the specified course key. + """ + return reverse('openedx.course_bookmarks.home', args=[course_key]) diff --git a/openedx/features/course_experience/course_tools.py b/openedx/features/course_experience/course_tools.py new file mode 100644 index 0000000000..bf36e14fe6 --- /dev/null +++ b/openedx/features/course_experience/course_tools.py @@ -0,0 +1,67 @@ +""" +Support for course tool plugins. +""" +from openedx.core.lib.api.plugins import PluginManager + +# Stevedore extension point namespace +COURSE_TOOLS_NAMESPACE = 'openedx.course_tool' + + +class CourseTool(object): + """ + This is an optional base class for Course Tool plugins. + + Plugin implementations inside this repo should subclass CourseTool to get + useful default behavior, and to add clarity to the code. This base class is + not a requirement, and plugin implementations outside of this repo should + simply follow the contract defined below. + """ + + @classmethod + def is_enabled(cls, course_key): + """ + Returns true if this tool is enabled for the specified course key. + """ + return True + + @classmethod + def title(cls, course_key): + """ + Returns the title for the course tool. + """ + raise NotImplementedError("Must specify a title for a course tool.") + + @classmethod + def icon_classes(cls, course_key): + """ + Returns the icon classes needed to represent this tool. + + For example, return an icon from font-awasome.css, like 'fa fa-star'. + """ + raise NotImplementedError("Must specify an icon for a course tool.") + + @classmethod + def url(cls, course_key): + """ + Returns the URL for this tool for the specified course key. + """ + raise NotImplementedError("Must specify a url for a course tool.") + + +class CourseToolsPluginManager(PluginManager): + """ + Manager for all of the course tools that have been made available. + + Course tool implementation can subclass `CourseTool` or can implement + the required class methods themselves. + """ + NAMESPACE = COURSE_TOOLS_NAMESPACE + + @classmethod + def get_course_tools(cls): + """ + Returns the list of available course tools in their canonical order. + """ + course_tools = cls.get_available_plugins().values() + course_tools.sort(key=lambda course_tool: course_tool.title()) + return course_tools diff --git a/openedx/features/course_experience/plugins.py b/openedx/features/course_experience/plugins.py new file mode 100644 index 0000000000..611c348382 --- /dev/null +++ b/openedx/features/course_experience/plugins.py @@ -0,0 +1,79 @@ +""" +Platform plugins to support the course experience. + +This includes any locally defined CourseTools. +""" + +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ + +from . import UNIFIED_COURSE_TAB_FLAG, SHOW_REVIEWS_TOOL_FLAG +from views.course_reviews import CourseReviewsModuleFragmentView +from course_tools import CourseTool + + +class CourseUpdatesTool(CourseTool): + """ + The course updates tool. + """ + @classmethod + def title(cls): + """ + Returns the title of this tool. + """ + return _('Updates') + + @classmethod + def icon_classes(cls): + """ + Returns icon classes needed to represent this tool. + """ + return 'fa fa-newspaper-o' + + @classmethod + def is_enabled(cls, course_key): + """ + Returns True if this tool is enabled for the specified course key. + """ + return UNIFIED_COURSE_TAB_FLAG.is_enabled(course_key) + + @classmethod + def url(cls, course_key): + """ + Returns the URL for this tool for the specified course key. + """ + return reverse('openedx.course_experience.course_updates', args=[course_key]) + + +class CourseReviewsTool(CourseTool): + """ + The course reviews tool. + """ + @classmethod + def title(cls): + """ + Returns the title of this tool. + """ + return _('Reviews') + + @classmethod + def icon_classes(cls): + """ + Returns icon classes needed to represent this tool. + """ + return 'fa fa-star' + + @classmethod + def is_enabled(cls, course_key): + """ + Returns True if this tool is enabled for the specified course key. + """ + reviews_configured = CourseReviewsModuleFragmentView.is_configured() + return SHOW_REVIEWS_TOOL_FLAG.is_enabled(course_key) and reviews_configured + + @classmethod + def url(cls, course_key): + """ + Returns the URL for this tool for the specified course key. + """ + return reverse('openedx.course_experience.course_reviews', args=[course_key]) diff --git a/openedx/features/course_experience/templates/course_experience/course-home-fragment.html b/openedx/features/course_experience/templates/course_experience/course-home-fragment.html index 9b0a513307..21abafd7fe 100644 --- a/openedx/features/course_experience/templates/course_experience/course-home-fragment.html +++ b/openedx/features/course_experience/templates/course_experience/course-home-fragment.html @@ -15,6 +15,7 @@ from django_comment_client.permissions import has_permission from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_string from openedx.core.djangolib.markup import HTML from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG, SHOW_REVIEWS_TOOL_FLAG +from openedx.features.course_experience.course_tools import CourseToolsPluginManager %> <%block name="content"> @@ -66,33 +67,26 @@ from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG, SHOW_REV ${HTML(outline_fragment.body_html())}