Merge pull request #8367 from edx/diana/merge-course-view-and-tab
Refactor and merge CourseViewType and CourseTab.
This commit is contained in:
@@ -5,16 +5,16 @@ Registers the CCX feature for the edX platform.
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from openedx.core.djangoapps.course_views.course_views import CourseViewType
|
||||
from xmodule.tabs import CourseTab
|
||||
from student.roles import CourseCcxCoachRole
|
||||
|
||||
|
||||
class CcxCourseViewType(CourseViewType):
|
||||
class CcxCourseTab(CourseTab):
|
||||
"""
|
||||
The representation of the CCX course view type.
|
||||
The representation of the CCX course tab
|
||||
"""
|
||||
|
||||
name = "ccx_coach"
|
||||
type = "ccx_coach"
|
||||
title = _("CCX Coach")
|
||||
view_name = "ccx_coach_dashboard"
|
||||
is_dynamic = True # The CCX view is dynamically added to the set of tabs when it is enabled
|
||||
|
||||
@@ -6,15 +6,15 @@ a user has on an article.
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from courseware.tabs import EnrolledCourseViewType
|
||||
from courseware.tabs import EnrolledTab
|
||||
|
||||
|
||||
class WikiCourseViewType(EnrolledCourseViewType):
|
||||
class WikiTab(EnrolledTab):
|
||||
"""
|
||||
Defines the Wiki view type that is shown as a course tab.
|
||||
"""
|
||||
|
||||
name = "wiki"
|
||||
type = "wiki"
|
||||
title = _('Wiki')
|
||||
view_name = "course_wiki"
|
||||
is_hideable = True
|
||||
@@ -28,4 +28,4 @@ class WikiCourseViewType(EnrolledCourseViewType):
|
||||
return False
|
||||
if course.allow_public_wiki_access:
|
||||
return True
|
||||
return super(WikiCourseViewType, cls).is_enabled(course, user=user)
|
||||
return super(WikiTab, cls).is_enabled(course, user=user)
|
||||
|
||||
@@ -7,12 +7,12 @@ from django.utils.translation import ugettext as _
|
||||
|
||||
from courseware.access import has_access
|
||||
from courseware.entrance_exams import user_must_complete_entrance_exam
|
||||
from openedx.core.djangoapps.course_views.course_views import CourseViewTypeManager, CourseViewType, StaticTab
|
||||
from openedx.core.lib.course_tabs import CourseTabPluginManager
|
||||
from student.models import CourseEnrollment
|
||||
from xmodule.tabs import CourseTab, CourseTabList, key_checker
|
||||
|
||||
|
||||
class EnrolledCourseViewType(CourseViewType):
|
||||
class EnrolledTab(CourseTab):
|
||||
"""
|
||||
A base class for any view types that require a user to be enrolled.
|
||||
"""
|
||||
@@ -23,22 +23,22 @@ class EnrolledCourseViewType(CourseViewType):
|
||||
return CourseEnrollment.is_enrolled(user, course.id) or has_access(user, 'staff', course, course.id)
|
||||
|
||||
|
||||
class CoursewareViewType(EnrolledCourseViewType):
|
||||
class CoursewareTab(EnrolledTab):
|
||||
"""
|
||||
The main courseware view.
|
||||
"""
|
||||
name = 'courseware'
|
||||
type = 'courseware'
|
||||
title = _('Courseware')
|
||||
priority = 10
|
||||
view_name = 'courseware'
|
||||
is_movable = False
|
||||
|
||||
|
||||
class CourseInfoViewType(CourseViewType):
|
||||
class CourseInfoTab(CourseTab):
|
||||
"""
|
||||
The course info view.
|
||||
"""
|
||||
name = 'course_info'
|
||||
type = 'course_info'
|
||||
title = _('Course Info')
|
||||
priority = 20
|
||||
view_name = 'info'
|
||||
@@ -50,27 +50,28 @@ class CourseInfoViewType(CourseViewType):
|
||||
return True
|
||||
|
||||
|
||||
class SyllabusCourseViewType(EnrolledCourseViewType):
|
||||
class SyllabusTab(EnrolledTab):
|
||||
"""
|
||||
A tab for the course syllabus.
|
||||
"""
|
||||
name = 'syllabus'
|
||||
type = 'syllabus'
|
||||
title = _('Syllabus')
|
||||
priority = 30
|
||||
view_name = 'syllabus'
|
||||
allow_multiple = True
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls, course, user=None): # pylint: disable=unused-argument
|
||||
if not super(SyllabusCourseViewType, cls).is_enabled(course, user=user):
|
||||
if not super(SyllabusTab, cls).is_enabled(course, user=user):
|
||||
return False
|
||||
return getattr(course, 'syllabus_present', False)
|
||||
|
||||
|
||||
class ProgressCourseViewType(EnrolledCourseViewType):
|
||||
class ProgressTab(EnrolledTab):
|
||||
"""
|
||||
The course progress view.
|
||||
"""
|
||||
name = 'progress'
|
||||
type = 'progress'
|
||||
title = _('Progress')
|
||||
priority = 40
|
||||
view_name = 'progress'
|
||||
@@ -78,12 +79,12 @@ class ProgressCourseViewType(EnrolledCourseViewType):
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls, course, user=None): # pylint: disable=unused-argument
|
||||
if not super(ProgressCourseViewType, cls).is_enabled(course, user=user):
|
||||
if not super(ProgressTab, cls).is_enabled(course, user=user):
|
||||
return False
|
||||
return not course.hide_progress_tab
|
||||
|
||||
|
||||
class TextbookCourseViewsBase(CourseViewType):
|
||||
class TextbookTabsBase(CourseTab):
|
||||
"""
|
||||
Abstract class for textbook collection tabs classes.
|
||||
"""
|
||||
@@ -104,17 +105,17 @@ class TextbookCourseViewsBase(CourseViewType):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class TextbookCourseViews(TextbookCourseViewsBase):
|
||||
class TextbookTabs(TextbookTabsBase):
|
||||
"""
|
||||
A tab representing the collection of all textbook tabs.
|
||||
"""
|
||||
name = 'textbooks'
|
||||
type = 'textbooks'
|
||||
priority = None
|
||||
view_name = 'book'
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls, course, user=None): # pylint: disable=unused-argument
|
||||
parent_is_enabled = super(TextbookCourseViews, cls).is_enabled(course, user)
|
||||
parent_is_enabled = super(TextbookTabs, cls).is_enabled(course, user)
|
||||
return settings.FEATURES.get('ENABLE_TEXTBOOK') and parent_is_enabled
|
||||
|
||||
@classmethod
|
||||
@@ -128,11 +129,11 @@ class TextbookCourseViews(TextbookCourseViewsBase):
|
||||
)
|
||||
|
||||
|
||||
class PDFTextbookCourseViews(TextbookCourseViewsBase):
|
||||
class PDFTextbookTabs(TextbookTabsBase):
|
||||
"""
|
||||
A tab representing the collection of all PDF textbook tabs.
|
||||
"""
|
||||
name = 'pdf_textbooks'
|
||||
type = 'pdf_textbooks'
|
||||
priority = None
|
||||
view_name = 'pdf_book'
|
||||
|
||||
@@ -147,11 +148,11 @@ class PDFTextbookCourseViews(TextbookCourseViewsBase):
|
||||
)
|
||||
|
||||
|
||||
class HtmlTextbookCourseViews(TextbookCourseViewsBase):
|
||||
class HtmlTextbookTabs(TextbookTabsBase):
|
||||
"""
|
||||
A tab representing the collection of all Html textbook tabs.
|
||||
"""
|
||||
name = 'html_textbooks'
|
||||
type = 'html_textbooks'
|
||||
priority = None
|
||||
view_name = 'html_book'
|
||||
|
||||
@@ -166,89 +167,6 @@ class HtmlTextbookCourseViews(TextbookCourseViewsBase):
|
||||
)
|
||||
|
||||
|
||||
class StaticCourseViewType(CourseViewType):
|
||||
"""
|
||||
The view type that shows a static tab.
|
||||
"""
|
||||
name = 'static_tab'
|
||||
is_default = False # A static tab is never added to a course by default
|
||||
allow_multiple = True
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls, course, user=None): # pylint: disable=unused-argument
|
||||
"""
|
||||
Static tabs are viewable to everyone, even anonymous users.
|
||||
"""
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def validate(cls, tab_dict, raise_error=True):
|
||||
"""
|
||||
Ensures that the specified tab_dict is valid.
|
||||
"""
|
||||
return (super(StaticCourseViewType, cls).validate(tab_dict, raise_error)
|
||||
and key_checker(['name', 'url_slug'])(tab_dict, raise_error))
|
||||
|
||||
@classmethod
|
||||
def create_tab(cls, tab_dict):
|
||||
"""
|
||||
Returns the tab that will be shown to represent an instance of a view.
|
||||
"""
|
||||
return StaticTab(tab_dict)
|
||||
|
||||
|
||||
class ExternalDiscussionCourseViewType(EnrolledCourseViewType):
|
||||
"""
|
||||
A course view links to an external discussion service.
|
||||
"""
|
||||
|
||||
name = 'external_discussion'
|
||||
# Translators: 'Discussion' refers to the tab in the courseware that leads to the discussion forums
|
||||
title = _('Discussion')
|
||||
priority = None
|
||||
|
||||
@classmethod
|
||||
def create_tab(cls, tab_dict):
|
||||
"""
|
||||
Returns the tab that will be shown to represent an instance of a view.
|
||||
"""
|
||||
return LinkTab(tab_dict, cls.title)
|
||||
|
||||
@classmethod
|
||||
def validate(cls, tab_dict, raise_error=True):
|
||||
""" Validate that the tab_dict for this course view has the necessary information to render. """
|
||||
return (super(ExternalDiscussionCourseViewType, cls).validate(tab_dict, raise_error) and
|
||||
key_checker(['link'])(tab_dict, raise_error))
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls, course, user=None): # pylint: disable=unused-argument
|
||||
if not super(ExternalDiscussionCourseViewType, cls).is_enabled(course, user=user):
|
||||
return False
|
||||
return course.discussion_link
|
||||
|
||||
|
||||
class ExternalLinkCourseViewType(EnrolledCourseViewType):
|
||||
"""
|
||||
A course view containing an external link.
|
||||
"""
|
||||
name = 'external_link'
|
||||
priority = None
|
||||
is_default = False # An external link tab is not added to a course by default
|
||||
|
||||
@classmethod
|
||||
def create_tab(cls, tab_dict):
|
||||
"""
|
||||
Returns the tab that will be shown to represent an instance of a view.
|
||||
"""
|
||||
return LinkTab(tab_dict)
|
||||
|
||||
@classmethod
|
||||
def validate(cls, tab_dict, raise_error=True):
|
||||
""" Validate that the tab_dict for this course view has the necessary information to render. """
|
||||
return (super(ExternalLinkCourseViewType, cls).validate(tab_dict, raise_error) and
|
||||
key_checker(['link', 'name'])(tab_dict, raise_error))
|
||||
|
||||
|
||||
class LinkTab(CourseTab):
|
||||
"""
|
||||
Abstract class for tabs that contain external links.
|
||||
@@ -264,11 +182,9 @@ class LinkTab(CourseTab):
|
||||
|
||||
self.type = tab_dict['type']
|
||||
|
||||
super(LinkTab, self).__init__(
|
||||
name=tab_dict['name'] if tab_dict else name,
|
||||
tab_id=None,
|
||||
link_func=link_value_func,
|
||||
)
|
||||
tab_dict['link_func'] = link_value_func
|
||||
|
||||
super(LinkTab, self).__init__(tab_dict)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key == 'link':
|
||||
@@ -292,6 +208,49 @@ class LinkTab(CourseTab):
|
||||
return False
|
||||
return self.link_value == other.get('link')
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls, course, user=None): # pylint: disable=unused-argument
|
||||
return True
|
||||
|
||||
|
||||
class ExternalDiscussionCourseTab(LinkTab):
|
||||
"""
|
||||
A course tab that links to an external discussion service.
|
||||
"""
|
||||
|
||||
type = 'external_discussion'
|
||||
# Translators: 'Discussion' refers to the tab in the courseware that leads to the discussion forums
|
||||
title = _('Discussion')
|
||||
priority = None
|
||||
|
||||
@classmethod
|
||||
def validate(cls, tab_dict, raise_error=True):
|
||||
""" Validate that the tab_dict for this course tab has the necessary information to render. """
|
||||
return (super(ExternalDiscussionCourseTab, cls).validate(tab_dict, raise_error) and
|
||||
key_checker(['link'])(tab_dict, raise_error))
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls, course, user=None): # pylint: disable=unused-argument
|
||||
if not super(ExternalDiscussionCourseTab, cls).is_enabled(course, user=user):
|
||||
return False
|
||||
return course.discussion_link
|
||||
|
||||
|
||||
class ExternalLinkCourseTab(LinkTab):
|
||||
"""
|
||||
A course tab containing an external link.
|
||||
"""
|
||||
type = 'external_link'
|
||||
priority = None
|
||||
is_default = False # An external link tab is not added to a course by default
|
||||
allow_multiple = True
|
||||
|
||||
@classmethod
|
||||
def validate(cls, tab_dict, raise_error=True):
|
||||
""" Validate that the tab_dict for this course tab has the necessary information to render. """
|
||||
return (super(ExternalLinkCourseTab, cls).validate(tab_dict, raise_error) and
|
||||
key_checker(['link', 'name'])(tab_dict, raise_error))
|
||||
|
||||
|
||||
class SingleTextbookTab(CourseTab):
|
||||
"""
|
||||
@@ -308,7 +267,11 @@ class SingleTextbookTab(CourseTab):
|
||||
""" Constructs a link for textbooks from a view name, a course, and an index. """
|
||||
return reverse_func(view_name, args=[unicode(course.id), index])
|
||||
|
||||
super(SingleTextbookTab, self).__init__(name, tab_id, link_func)
|
||||
tab_dict = dict()
|
||||
tab_dict['name'] = name
|
||||
tab_dict['tab_id'] = tab_id
|
||||
tab_dict['link_func'] = link_func
|
||||
super(SingleTextbookTab, self).__init__(tab_dict)
|
||||
|
||||
def to_json(self):
|
||||
raise NotImplementedError('SingleTextbookTab should not be serialized.')
|
||||
@@ -347,9 +310,9 @@ def _get_dynamic_tabs(course, user):
|
||||
instead added dynamically based upon the user's role.
|
||||
"""
|
||||
dynamic_tabs = list()
|
||||
for tab_type in CourseViewTypeManager.get_course_view_types():
|
||||
for tab_type in CourseTabPluginManager.get_tab_types():
|
||||
if getattr(tab_type, "is_dynamic", False):
|
||||
tab = tab_type.create_tab(dict())
|
||||
tab = tab_type(dict())
|
||||
if tab.is_enabled(course, user=user):
|
||||
dynamic_tabs.append(tab)
|
||||
dynamic_tabs.sort(key=lambda dynamic_tab: dynamic_tab.name)
|
||||
|
||||
@@ -11,8 +11,8 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
|
||||
from courseware.courses import get_course_by_id
|
||||
from courseware.tabs import (
|
||||
get_course_tab_list, CoursewareViewType, CourseInfoViewType, ProgressCourseViewType,
|
||||
StaticCourseViewType, ExternalDiscussionCourseViewType, ExternalLinkCourseViewType
|
||||
get_course_tab_list, CoursewareTab, CourseInfoTab, ProgressTab,
|
||||
ExternalDiscussionCourseTab, ExternalLinkCourseTab
|
||||
)
|
||||
from courseware.tests.helpers import get_request_for_user, LoginEnrollmentTestCase
|
||||
from courseware.tests.factories import InstructorFactory, StaffFactory
|
||||
@@ -85,7 +85,7 @@ class TabTestCase(ModuleStoreTestCase):
|
||||
Can be 'None' if the given tab class does not have any keys to validate.
|
||||
"""
|
||||
# create tab
|
||||
tab = tab_class.create_tab(tab_dict=dict_tab)
|
||||
tab = tab_class(tab_dict=dict_tab)
|
||||
|
||||
# name is as expected
|
||||
self.assertEqual(tab.name, expected_name)
|
||||
@@ -475,17 +475,17 @@ class TabListTestCase(TabTestCase):
|
||||
# invalid tabs
|
||||
self.invalid_tabs = [
|
||||
# less than 2 tabs
|
||||
[{'type': CoursewareViewType.name}],
|
||||
[{'type': CoursewareTab.type}],
|
||||
# missing course_info
|
||||
[{'type': CoursewareViewType.name}, {'type': 'discussion', 'name': 'fake_name'}],
|
||||
[{'type': CoursewareTab.type}, {'type': 'discussion', 'name': 'fake_name'}],
|
||||
# incorrect order
|
||||
[{'type': CourseInfoViewType.name, 'name': 'fake_name'}, {'type': CoursewareViewType.name}],
|
||||
[{'type': CourseInfoTab.type, 'name': 'fake_name'}, {'type': CoursewareTab.type}],
|
||||
]
|
||||
|
||||
# tab types that should appear only once
|
||||
unique_tab_types = [
|
||||
CoursewareViewType.name,
|
||||
CourseInfoViewType.name,
|
||||
CoursewareTab.type,
|
||||
CourseInfoTab.type,
|
||||
'textbooks',
|
||||
'pdf_textbooks',
|
||||
'html_textbooks',
|
||||
@@ -493,8 +493,8 @@ class TabListTestCase(TabTestCase):
|
||||
|
||||
for unique_tab_type in unique_tab_types:
|
||||
self.invalid_tabs.append([
|
||||
{'type': CoursewareViewType.name},
|
||||
{'type': CourseInfoViewType.name, 'name': 'fake_name'},
|
||||
{'type': CoursewareTab.type},
|
||||
{'type': CourseInfoTab.type, 'name': 'fake_name'},
|
||||
# add the unique tab multiple times
|
||||
{'type': unique_tab_type},
|
||||
{'type': unique_tab_type},
|
||||
@@ -502,26 +502,27 @@ class TabListTestCase(TabTestCase):
|
||||
|
||||
# valid tabs
|
||||
self.valid_tabs = [
|
||||
# empty list
|
||||
# any empty list is valid because a default list of tabs will be
|
||||
# generated to replace the empty list.
|
||||
[],
|
||||
# all valid tabs
|
||||
[
|
||||
{'type': CoursewareViewType.name},
|
||||
{'type': CourseInfoViewType.name, 'name': 'fake_name'},
|
||||
{'type': CoursewareTab.type},
|
||||
{'type': CourseInfoTab.type, 'name': 'fake_name'},
|
||||
{'type': 'discussion', 'name': 'fake_name'},
|
||||
{'type': ExternalLinkCourseViewType.name, 'name': 'fake_name', 'link': 'fake_link'},
|
||||
{'type': ExternalLinkCourseTab.type, 'name': 'fake_name', 'link': 'fake_link'},
|
||||
{'type': 'textbooks'},
|
||||
{'type': 'pdf_textbooks'},
|
||||
{'type': 'html_textbooks'},
|
||||
{'type': ProgressCourseViewType.name, 'name': 'fake_name'},
|
||||
{'type': StaticCourseViewType.name, 'name': 'fake_name', 'url_slug': 'schlug'},
|
||||
{'type': ProgressTab.type, 'name': 'fake_name'},
|
||||
{'type': xmodule_tabs.StaticTab.type, 'name': 'fake_name', 'url_slug': 'schlug'},
|
||||
{'type': 'syllabus'},
|
||||
],
|
||||
# with external discussion
|
||||
[
|
||||
{'type': CoursewareViewType.name},
|
||||
{'type': CourseInfoViewType.name, 'name': 'fake_name'},
|
||||
{'type': ExternalDiscussionCourseViewType.name, 'name': 'fake_name', 'link': 'fake_link'}
|
||||
{'type': CoursewareTab.type},
|
||||
{'type': CourseInfoTab.type, 'name': 'fake_name'},
|
||||
{'type': ExternalDiscussionCourseTab.type, 'name': 'fake_name', 'link': 'fake_link'}
|
||||
],
|
||||
]
|
||||
|
||||
@@ -550,8 +551,8 @@ class ValidateTabsTestCase(TabListTestCase):
|
||||
tab_list = xmodule_tabs.CourseTabList()
|
||||
self.assertEquals(
|
||||
len(tab_list.from_json([
|
||||
{'type': CoursewareViewType.name},
|
||||
{'type': CourseInfoViewType.name, 'name': 'fake_name'},
|
||||
{'type': CoursewareTab.type},
|
||||
{'type': CourseInfoTab.type, 'name': 'fake_name'},
|
||||
{'type': 'no_such_type'}
|
||||
])),
|
||||
2
|
||||
@@ -660,10 +661,10 @@ class ProgressTestCase(TabTestCase):
|
||||
def check_progress_tab(self):
|
||||
"""Helper function for verifying the progress tab."""
|
||||
return self.check_tab(
|
||||
tab_class=ProgressCourseViewType,
|
||||
dict_tab={'type': ProgressCourseViewType.name, 'name': 'same'},
|
||||
tab_class=ProgressTab,
|
||||
dict_tab={'type': ProgressTab.type, 'name': 'same'},
|
||||
expected_link=self.reverse('progress', args=[self.course.id.to_deprecated_string()]),
|
||||
expected_tab_id=ProgressCourseViewType.name,
|
||||
expected_tab_id=ProgressTab.type,
|
||||
invalid_dict_tab=None,
|
||||
)
|
||||
|
||||
@@ -692,8 +693,8 @@ class StaticTabTestCase(TabTestCase):
|
||||
url_slug = 'schmug'
|
||||
|
||||
tab = self.check_tab(
|
||||
tab_class=StaticCourseViewType,
|
||||
dict_tab={'type': StaticCourseViewType.name, 'name': 'same', 'url_slug': url_slug},
|
||||
tab_class=xmodule_tabs.StaticTab,
|
||||
dict_tab={'type': xmodule_tabs.StaticTab.type, 'name': 'same', 'url_slug': url_slug},
|
||||
expected_link=self.reverse('static_tab', args=[self.course.id.to_deprecated_string(), url_slug]),
|
||||
expected_tab_id='static_tab_schmug',
|
||||
invalid_dict_tab=self.fake_dict_tab,
|
||||
|
||||
@@ -1150,9 +1150,9 @@ def notification_image_for_tab(course_tab, user, course):
|
||||
"""
|
||||
|
||||
tab_notification_handlers = {
|
||||
StaffGradingTab.name: open_ended_notifications.staff_grading_notifications,
|
||||
PeerGradingTab.name: open_ended_notifications.peer_grading_notifications,
|
||||
OpenEndedGradingTab.name: open_ended_notifications.combined_notifications
|
||||
StaffGradingTab.type: open_ended_notifications.staff_grading_notifications,
|
||||
PeerGradingTab.type: open_ended_notifications.peer_grading_notifications,
|
||||
OpenEndedGradingTab.type: open_ended_notifications.combined_notifications
|
||||
}
|
||||
|
||||
if course_tab.name in tab_notification_handlers:
|
||||
|
||||
@@ -25,7 +25,7 @@ from openedx.core.djangoapps.course_groups.cohorts import (
|
||||
get_course_cohorts,
|
||||
is_commentable_cohorted
|
||||
)
|
||||
from courseware.tabs import EnrolledCourseViewType
|
||||
from courseware.tabs import EnrolledTab
|
||||
from courseware.access import has_access
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from ccx.overrides import get_current_ccx
|
||||
@@ -49,19 +49,19 @@ PAGES_NEARBY_DELTA = 2
|
||||
log = logging.getLogger("edx.discussions")
|
||||
|
||||
|
||||
class DiscussionCourseViewType(EnrolledCourseViewType):
|
||||
class DiscussionTab(EnrolledTab):
|
||||
"""
|
||||
A tab for the cs_comments_service forums.
|
||||
"""
|
||||
|
||||
name = 'discussion'
|
||||
type = 'discussion'
|
||||
title = _('Discussion')
|
||||
priority = None
|
||||
view_name = 'django_comment_client.forum.views.forum_form_discussion'
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls, course, user=None):
|
||||
if not super(DiscussionCourseViewType, cls).is_enabled(course, user):
|
||||
if not super(DiscussionTab, cls).is_enabled(course, user):
|
||||
return False
|
||||
|
||||
if settings.FEATURES.get('CUSTOM_COURSES_EDX', False):
|
||||
|
||||
@@ -4,15 +4,15 @@ Registers the "edX Notes" feature for the edX platform.
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from courseware.tabs import EnrolledCourseViewType
|
||||
from courseware.tabs import EnrolledTab
|
||||
|
||||
|
||||
class EdxNotesCourseViewType(EnrolledCourseViewType):
|
||||
class EdxNotesTab(EnrolledTab):
|
||||
"""
|
||||
The representation of the edX Notes course view type.
|
||||
The representation of the edX Notes course tab type.
|
||||
"""
|
||||
|
||||
name = "edxnotes"
|
||||
type = "edxnotes"
|
||||
title = _("Notes")
|
||||
view_name = "edxnotes"
|
||||
|
||||
@@ -25,6 +25,6 @@ class EdxNotesCourseViewType(EnrolledCourseViewType):
|
||||
settings (dict): a dict of configuration settings
|
||||
user (User): the user interacting with the course
|
||||
"""
|
||||
if not super(EdxNotesCourseViewType, cls).is_enabled(course, user=user):
|
||||
if not super(EdxNotesTab, cls).is_enabled(course, user=user):
|
||||
return False
|
||||
return course.edxnotes
|
||||
|
||||
@@ -26,6 +26,7 @@ from lms.djangoapps.lms_xblock.runtime import quote_slashes
|
||||
from openedx.core.lib.xblock_utils import wrap_xblock
|
||||
from xmodule.html_module import HtmlDescriptor
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.tabs import CourseTab
|
||||
from xblock.field_data import DictFieldData
|
||||
from xblock.fields import ScopeIds
|
||||
from courseware.access import has_access
|
||||
@@ -38,7 +39,6 @@ from course_modes.models import CourseMode, CourseModesArchive
|
||||
from student.roles import CourseFinanceAdminRole, CourseSalesAdminRole
|
||||
from certificates.models import CertificateGenerationConfiguration
|
||||
from certificates import api as certs_api
|
||||
from openedx.core.djangoapps.course_views.course_views import CourseViewType
|
||||
|
||||
from class_dashboard.dashboard_data import get_section_display_name, get_array_section_has_problem
|
||||
from .tools import get_units_with_due_date, title_or_url, bulk_email_is_enabled_for_course
|
||||
@@ -47,12 +47,12 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InstructorDashboardViewType(CourseViewType):
|
||||
class InstructorDashboardTab(CourseTab):
|
||||
"""
|
||||
Defines the Instructor Dashboard view type that is shown as a course tab.
|
||||
"""
|
||||
|
||||
name = "instructor"
|
||||
type = "instructor"
|
||||
title = _('Instructor')
|
||||
view_name = "instructor_dashboard"
|
||||
is_dynamic = True # The "Instructor" tab is instead dynamically added when it is enabled
|
||||
|
||||
@@ -9,7 +9,7 @@ from django.http import Http404
|
||||
from edxmako.shortcuts import render_to_response
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from courseware.courses import get_course_with_access
|
||||
from courseware.tabs import EnrolledCourseViewType
|
||||
from courseware.tabs import EnrolledTab
|
||||
from notes.models import Note
|
||||
from notes.utils import notes_enabled_for_course
|
||||
from xmodule.annotator_token import retrieve_token
|
||||
@@ -40,16 +40,16 @@ def notes(request, course_id):
|
||||
return render_to_response('notes.html', context)
|
||||
|
||||
|
||||
class NotesCourseViewType(EnrolledCourseViewType):
|
||||
class NotesTab(EnrolledTab):
|
||||
"""
|
||||
A tab for the course notes.
|
||||
"""
|
||||
name = 'notes'
|
||||
type = 'notes'
|
||||
title = _("My Notes")
|
||||
view_name = "notes"
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls, course, user=None):
|
||||
if not super(NotesCourseViewType, cls).is_enabled(course, user):
|
||||
if not super(NotesTab, cls).is_enabled(course, user):
|
||||
return False
|
||||
return settings.FEATURES.get('ENABLE_STUDENT_NOTES') and "notes" in course.advanced_modules
|
||||
|
||||
@@ -4,11 +4,10 @@ from django.views.decorators.cache import cache_control
|
||||
from edxmako.shortcuts import render_to_response
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from openedx.core.djangoapps.course_views.course_views import CourseViewType
|
||||
|
||||
from courseware.courses import get_course_with_access
|
||||
from courseware.access import has_access
|
||||
from courseware.tabs import EnrolledCourseViewType
|
||||
from courseware.tabs import EnrolledTab
|
||||
|
||||
from xmodule.open_ended_grading_classes.grading_service_module import GradingServiceError
|
||||
import json
|
||||
@@ -66,11 +65,11 @@ ALERT_DICT = {
|
||||
}
|
||||
|
||||
|
||||
class StaffGradingTab(CourseViewType):
|
||||
class StaffGradingTab(EnrolledTab):
|
||||
"""
|
||||
A tab for staff grading.
|
||||
"""
|
||||
name = 'staff_grading'
|
||||
type = 'staff_grading'
|
||||
title = _("Staff grading")
|
||||
view_name = "staff_grading"
|
||||
|
||||
@@ -81,11 +80,11 @@ class StaffGradingTab(CourseViewType):
|
||||
return "combinedopenended" in course.advanced_modules
|
||||
|
||||
|
||||
class PeerGradingTab(EnrolledCourseViewType):
|
||||
class PeerGradingTab(EnrolledTab):
|
||||
"""
|
||||
A tab for peer grading.
|
||||
"""
|
||||
name = 'peer_grading'
|
||||
type = 'peer_grading'
|
||||
# Translators: "Peer grading" appears on a tab that allows
|
||||
# students to view open-ended problems that require grading
|
||||
title = _("Peer grading")
|
||||
@@ -98,11 +97,11 @@ class PeerGradingTab(EnrolledCourseViewType):
|
||||
return "combinedopenended" in course.advanced_modules
|
||||
|
||||
|
||||
class OpenEndedGradingTab(EnrolledCourseViewType):
|
||||
class OpenEndedGradingTab(EnrolledTab):
|
||||
"""
|
||||
A tab for open ended grading.
|
||||
"""
|
||||
name = 'open_ended'
|
||||
type = 'open_ended'
|
||||
# Translators: "Open Ended Panel" appears on a tab that, when clicked, opens up a panel that
|
||||
# displays information about open-ended problems that a user has submitted or needs to grade
|
||||
title = _("Open Ended Panel")
|
||||
|
||||
@@ -3,16 +3,16 @@ Definition of the course team feature.
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from courseware.tabs import EnrolledCourseViewType
|
||||
from courseware.tabs import EnrolledTab
|
||||
from .views import is_feature_enabled
|
||||
|
||||
|
||||
class TeamsCourseViewType(EnrolledCourseViewType):
|
||||
class TeamsTab(EnrolledTab):
|
||||
"""
|
||||
The representation of the course teams view type.
|
||||
"""
|
||||
|
||||
name = "teams"
|
||||
type = "teams"
|
||||
title = _("Teams")
|
||||
view_name = "teams_dashboard"
|
||||
|
||||
@@ -24,7 +24,7 @@ class TeamsCourseViewType(EnrolledCourseViewType):
|
||||
course (CourseDescriptor): the course using the feature
|
||||
user (User): the user interacting with the course
|
||||
"""
|
||||
if not super(TeamsCourseViewType, cls).is_enabled(course, user=user):
|
||||
if not super(TeamsTab, cls).is_enabled(course, user=user):
|
||||
return False
|
||||
|
||||
return is_feature_enabled(course)
|
||||
|
||||
Reference in New Issue
Block a user