From 75d89e811543fece03f5ab2df213ffdc7037d482 Mon Sep 17 00:00:00 2001 From: Andy Armstrong Date: Mon, 30 Jan 2017 22:52:03 -0500 Subject: [PATCH] Implement a stub unified course tab --- lms/djangoapps/courseware/tabs.py | 14 +++- lms/djangoapps/courseware/views/views.py | 53 ++++++++++++++ lms/templates/courseware/course-outline.html | 12 ++++ .../courseware/unified-course-view.html | 72 +++++++++++++++++++ lms/urls.py | 15 ++++ 5 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 lms/templates/courseware/course-outline.html create mode 100644 lms/templates/courseware/unified-course-view.html diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 2da310d4f3..919cc8fccd 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -2,6 +2,8 @@ This module is essentially a broker to xmodule/tabs.py -- it was originally introduced to perform some LMS-specific tab display gymnastics for the Entrance Exams feature """ +import waffle + from django.conf import settings from django.utils.translation import ugettext as _, ugettext_noop @@ -9,7 +11,7 @@ from courseware.access import has_access from courseware.entrance_exams import user_can_skip_entrance_exam from openedx.core.lib.course_tabs import CourseTabPluginManager from student.models import CourseEnrollment -from xmodule.tabs import CourseTab, CourseTabList, key_checker +from xmodule.tabs import CourseTab, CourseTabList, key_checker, link_reverse_func class EnrolledTab(CourseTab): @@ -34,6 +36,16 @@ class CoursewareTab(EnrolledTab): is_movable = False is_default = False + @property + def link_func(self): + """ + Returns a function that computes the URL for this tab. + """ + if waffle.switch_is_active('unified_course_view'): + return link_reverse_func('unified_course_view') + else: + return link_reverse_func('courseware') + class CourseInfoTab(CourseTab): """ diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 482b6dddd4..57a6e88251 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -25,6 +25,7 @@ from django.http import ( QueryDict, ) from django.shortcuts import redirect +from django.template.loader import render_to_string from django.utils.decorators import method_decorator from django.utils.timezone import UTC from django.utils.translation import ugettext as _ @@ -1623,3 +1624,55 @@ def financial_assistance_form(request): } ], }) + + +class UnifiedCourseView(View): + """ + Unified view for a course. + """ + @method_decorator(login_required) + @method_decorator(ensure_csrf_cookie) + @method_decorator(cache_control(no_cache=True, no_store=True, must_revalidate=True)) + @method_decorator(ensure_valid_course_key) + def get(self, request, course_id): + """ + Displays the main view for the specified course. + + Arguments: + request: HTTP request + course_id (unicode): course id + """ + course_key = CourseKey.from_string(course_id) + course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) + + # Render the outline as a fragment + outline_fragment = CourseOutlineFragmentView().render_fragment(request, course_id=course_id) + + # Render the entire unified course view + context = { + 'csrf': csrf(request)['csrf_token'], + 'course': course, + 'outline_fragment': outline_fragment, + 'disable_courseware_js': True, + 'uses_pattern_library': True, + } + return render_to_response('courseware/unified-course-view.html', context) + + +class CourseOutlineFragmentView(FragmentView): + """ + Course outline fragment to be shown in the unified course view. + """ + + def render_fragment(self, request, course_id=None): + """ + Renders the course outline as a fragment. + """ + course_key = CourseKey.from_string(course_id) + course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) + context = { + 'csrf': csrf(request)['csrf_token'], + 'course': course, + } + html = render_to_string('courseware/course-outline.html', context) + return Fragment(html) diff --git a/lms/templates/courseware/course-outline.html b/lms/templates/courseware/course-outline.html new file mode 100644 index 0000000000..09ff7acfbf --- /dev/null +++ b/lms/templates/courseware/course-outline.html @@ -0,0 +1,12 @@ +## mako + +<%namespace name='static' file='../static_content.html'/> + +<%! +import json +from django.utils.translation import ugettext as _ +%> + +
+

Hello, world!

+
diff --git a/lms/templates/courseware/unified-course-view.html b/lms/templates/courseware/unified-course-view.html new file mode 100644 index 0000000000..27d1b07241 --- /dev/null +++ b/lms/templates/courseware/unified-course-view.html @@ -0,0 +1,72 @@ +## mako + +<%! main_css = "style-main-v2" %> + +<%page expression_filter="h"/> +<%inherit file="../main.html" /> +<%namespace name='static' file='../static_content.html'/> +<%def name="online_help_token()"><% return "courseware" %> +<%def name="course_name()"> +<% return _("{course_number} Courseware").format(course_number=course.display_number_with_default) %> + + +<%! +import json +from django.utils.translation import ugettext as _ +from django.template.defaultfilters import escapejs +from django.core.urlresolvers import reverse + +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 +%> + +<%block name="bodyclass">course + +<%block name="pagetitle">${course_name()} + +<%include file="../courseware/course_navigation.html" args="active_page='courseware'" /> + +<%block name="headextra"> +${HTML(outline_fragment.head_html())} + + +<%block name="js_extra"> +${HTML(outline_fragment.foot_html())} + + +<%block name="content"> +
+ +
+ ${HTML(outline_fragment.body_html())} +
+
+ diff --git a/lms/urls.py b/lms/urls.py index e5b6736bdd..2583fc9a77 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -11,6 +11,7 @@ from django.conf.urls.static import static from courseware.views.views import CourseTabView, EnrollStaffView, StaticCourseTabView from config_models.views import ConfigurationModelCurrentAPIView from courseware.views.index import CoursewareIndex +from courseware.views.views import UnifiedCourseView, CourseOutlineFragmentView from openedx.core.djangoapps.auth_exchange.views import LoginWithAccessTokenView from openedx.core.djangoapps.catalog.models import CatalogIntegration from openedx.core.djangoapps.programs.models import ProgramsApiConfig @@ -379,6 +380,20 @@ urlpatterns += ( name='html_book', ), + url( + r'^courses/{}/course/?$'.format( + settings.COURSE_ID_PATTERN, + ), + UnifiedCourseView.as_view(), + name='unified_course_view', + ), + url( + r'^courses/{}/course/outline?$'.format( + settings.COURSE_ID_PATTERN, + ), + CourseOutlineFragmentView.as_view(), + name='course_outline_fragment_view', + ), url( r'^courses/{}/courseware/?$'.format( settings.COURSE_ID_PATTERN,