This document describes how to extend the edX platform with a new tab that can be added to courses.

Background

An edX course has a notion of a set of tabs that present the student with information about an aspect of their experience:

In Studio, a course author can manage the list of tabs (called Pages in the UX):

Introducing a new course tab

The edX platform provides a Python entry point to allow new course tabs to be registered as plugins. At a high level, we recommend that you do the following:

The following is a more detailed list of the steps required to add a new course tab.

1. Add an entry point like this to your Python library's setup.py

Note that new_tab is the id of your tab, and example.NewTab is the fully qualified name of your new tab class.

entry_points={
    "openedx.course_tab": [
        "new_tab = example.NewTab",
    ]
}

2. Define your new tab class

Define your new tab class as a subclass of EnrolledTab, if the tab should only be shown to enrolled users, or CourseTab if unenrolled users should also be able to see it.

from courseware.tabs import CourseTab
 
 
class NewTab(CourseTab):
    """A new course tab."""

    name = "new_tab"
    title = ugettext_noop("New Tab")  # We don't have the user in this context, so we don't want to translate it at this level.
    view_name = "new_tab_view"

    @classmethod
    def is_enabled(cls, course, user=None):
        """Returns true if this tab is enabled."""
        return settings.FEATURES.get('NEW_TAB_ENABLED', False)

The key properties of a course tab are as follows:

PropertyDescriptionDefault
nameThe name of the tab. This name is used as the id of the tab when persisted in a course.(error)
titleThe title of the tab. This is typically shown as the tab's label.(error)
fragment_view_name

The name of the fragment view class that renders the tab's contents. This property should only be specified if the tab class uses TabFragmentViewMixin.

None
view_name

The name of the Django view that renders the tab. This field is required if fragment_view_name is not specified.

Note that for the moment all new tabs must be implemented as Django views. The following JIRA story proposes support for adding new tabs using xblocks: .

None
priorityThe relative priority of this tab. If specified, it affects the order in which this tab is added to a course. Lower priorities appear first, and the built-in tabs use priorities below 50. It is strongly recommended to use the default and allow the tabs to be sorted alphabetically.None
tab_idThe HTML id to be used when the tab is rendered.uses value of name
is_movableIf true, the author can move this tab to a different position.True
is_dynamicIf true, this tab will be shown dynamically to the user, instead of being persisted into the course's tabs. A good example is the "Instructor" tab which is shown only to course staff.False
is_defaultIf true, this tab will be added to the end of course's list of tabs if it is enabled. For example, the "Notes" tab appears automatically when Student Notes is enabled in a course. This tab will then be exported with the rest of the course. The list of tabs is refreshed after modifying the advanced settings.True
is_hideableIf true, an author can choose to hide this tab from their course.False
allow_multipleIf true, a course can add more than one instance of this view type.False

In addition, a tab can override any of the following class methods:

MethodSignatureDescription
is_enabled
def is_enabled(cls, course, user=None)
Returns true if this tab is enabled for the current course for the specified user. If user is None, this method is being called by Studio and should generally return True if the tab will be shown to at least some students.
validate
def validate(cls, tab_dict, raise_error=True)
Validates a dictionary representing a course tab. If raise_error then issues are raised as exceptions, else the function should return True if the dictionary is valid.

The course stores a static list of its tabs in the database, and this list is only updated when one of the following actions take place:

  1. You create a new course.
  2. You update the advanced settings for your course.

This means that if you have a pre-existing course then it won't immediately show a tab even after you've registered the new entry point.

3. Implement the view

You have two choices when implementing your new tab view:

  1. Implement a view which renders only the contents of your new tab
  2. Implement a full page view

Examples

Fragment Example: Discussions tab

The Discussions feature renders its tab as a web fragment. Here's how it works:

Full Page Example: Teams tab

This example is to explain how legacy tabs were created. For new tabs, please follow the fragment example.

A simple example of a full Django View is the "Teams" tab. Here's how it gets added to the platform:

Troubleshooting

If your new tab isn't showing up, try the following:

If your new tab type isn't returned then that means that the entry point registration didn't work. 

See Also