diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index 092a0be8c6..b39e2d6315 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -2,10 +2,11 @@ from collections import defaultdict from fs.errors import ResourceNotFoundError import logging import inspect +import re from path import path from django.http import Http404 - +from django.conf import settings from .module_render import get_module from xmodule.course_module import CourseDescriptor from xmodule.modulestore import Location, XML_MODULESTORE_TYPE @@ -294,3 +295,19 @@ def sort_by_announcement(courses): courses = sorted(courses, key=key) return courses + + +def get_cms_course_link_by_id(course_id): + """ + Returns a proto-relative link to course_index for editing the course in cms, assuming that the course is actually + cms-backed. If course_id is improperly formatted, just return the root of the cms + """ + format_str = r'^(?P[^/]+)/(?P[^/]+)/(?P[^/]+)$' + host = "//{}/".format(settings.CMS_BASE) # protocol-relative + m_obj = re.match(format_str, course_id) + if m_obj: + return "{host}{org}/{course}/course/{name}".format(host=host, + org=m_obj.group('org'), + course=m_obj.group('course'), + name=m_obj.group('name')) + return host diff --git a/lms/djangoapps/courseware/tests/test_courses.py b/lms/djangoapps/courseware/tests/test_courses.py index 60594602a4..20cb83a411 100644 --- a/lms/djangoapps/courseware/tests/test_courses.py +++ b/lms/djangoapps/courseware/tests/test_courses.py @@ -1,7 +1,10 @@ # -*- coding: utf-8 -*- from django.test import TestCase from django.http import Http404 -from courseware.courses import get_course_by_id +from django.test.utils import override_settings +from courseware.courses import get_course_by_id, get_cms_course_link_by_id + +CMS_BASE_TEST = 'testcms' class CoursesTest(TestCase): def test_get_course_by_id_invalid_chars(self): @@ -14,3 +17,12 @@ class CoursesTest(TestCase): get_course_by_id('MITx/foobar/statistics=introduction') get_course_by_id('MITx/foobar/business and management') get_course_by_id('MITx/foobar/NiñøJoséMaríáßç') + + @override_settings(CMS_BASE=CMS_BASE_TEST) + def test_get_cms_course_link_by_id(self): + """ + Tests that get_cms_course_link_by_id returns the right thing + """ + self.assertEqual("//{}/".format(CMS_BASE_TEST), get_cms_course_link_by_id("blah_bad_course_id")) + self.assertEqual("//{}/".format(CMS_BASE_TEST), get_cms_course_link_by_id("too/too/many/slashes")) + self.assertEqual("//{}/org/num/course/name".format(CMS_BASE_TEST), get_cms_course_link_by_id('org/num/name')) diff --git a/lms/djangoapps/instructor/views/legacy.py b/lms/djangoapps/instructor/views/legacy.py index b9295557d7..bcf2910582 100644 --- a/lms/djangoapps/instructor/views/legacy.py +++ b/lms/djangoapps/instructor/views/legacy.py @@ -33,7 +33,7 @@ from xmodule.html_module import HtmlDescriptor from courseware import grades from courseware.access import (has_access, get_access_group_name, course_beta_test_group_name) -from courseware.courses import get_course_with_access +from courseware.courses import get_course_with_access, get_cms_course_link_by_id from courseware.models import StudentModule from django_comment_common.models import (Role, FORUM_ROLE_ADMINISTRATOR, @@ -792,23 +792,30 @@ def instructor_dashboard(request, course_id): else: instructor_tasks = None + # determine if this is a studio-backed course so we can 1) provide a link to edit this course in studio + # 2) enable course email + is_studio_course = modulestore().get_modulestore_type(course_id) == MONGO_MODULESTORE_TYPE + + email_editor = None # HTML editor for email - if idash_mode == 'Email': + if idash_mode == 'Email' and is_studio_course: html_module = HtmlDescriptor(course.system, {'data': html_message}) email_editor = wrap_xmodule(html_module.get_html, html_module, 'xmodule_edit.html')() - else: - email_editor = None + + studio_url = None + if is_studio_course: + studio_url = get_cms_course_link_by_id(course_id) # Flag for whether or not we display the email tab (depending upon # what backing store this course using (Mongo vs. XML)) - if settings.MITX_FEATURES['ENABLE_INSTRUCTOR_EMAIL'] and \ - modulestore().get_modulestore_type(course_id) == MONGO_MODULESTORE_TYPE: + if settings.MITX_FEATURES['ENABLE_INSTRUCTOR_EMAIL'] and is_studio_course: show_email_tab = True # display course stats only if there is no other table to display: course_stats = None if not datatable: course_stats = get_course_stats_table() + #---------------------------------------- # context for rendering @@ -821,6 +828,7 @@ def instructor_dashboard(request, course_id): 'course_stats': course_stats, 'msg': msg, 'modeflag': {idash_mode: 'selectedmode'}, + 'studio_url': studio_url, 'to_option': email_to_option, # email 'subject': email_subject, # email @@ -843,7 +851,6 @@ def instructor_dashboard(request, course_id): return render_to_response('courseware/instructor_dashboard.html', context) - def _do_remote_gradebook(user, course, action, args=None, files=None): ''' Perform remote gradebook action. Returns msg, datatable. diff --git a/lms/envs/aws.py b/lms/envs/aws.py index a22fbc5bb6..35275036e5 100644 --- a/lms/envs/aws.py +++ b/lms/envs/aws.py @@ -111,6 +111,8 @@ SITE_NAME = ENV_TOKENS['SITE_NAME'] SESSION_ENGINE = ENV_TOKENS.get('SESSION_ENGINE', SESSION_ENGINE) SESSION_COOKIE_DOMAIN = ENV_TOKENS.get('SESSION_COOKIE_DOMAIN') +CMS_BASE = ENV_TOKENS.get('CMS_BASE', 'studio.edx.org') + # allow for environments to specify what cookie name our login subsystem should use # this is to fix a bug regarding simultaneous logins between edx.org and edge.edx.org which can # happen with some browsers (e.g. Firefox) diff --git a/lms/envs/common.py b/lms/envs/common.py index 4e70f3ade1..54d950bd94 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -355,6 +355,9 @@ DEBUG = False TEMPLATE_DEBUG = False USE_TZ = True +# CMS base +CMS_BASE = 'localhost:8001' + # Site info SITE_ID = 1 SITE_NAME = "edx.org" diff --git a/lms/static/sass/course/instructor/_instructor.scss b/lms/static/sass/course/instructor/_instructor.scss index eee4afffc6..6ec7f617ab 100644 --- a/lms/static/sass/course/instructor/_instructor.scss +++ b/lms/static/sass/course/instructor/_instructor.scss @@ -8,6 +8,12 @@ right: 2em; } + .studio-edit-link{ + position: absolute; + top: 3.5em; + right: 2em; + } + section.instructor-dashboard-content { @extend .content; padding: 40px; diff --git a/lms/templates/courseware/instructor_dashboard.html b/lms/templates/courseware/instructor_dashboard.html index fae76cca93..effa5852d8 100644 --- a/lms/templates/courseware/instructor_dashboard.html +++ b/lms/templates/courseware/instructor_dashboard.html @@ -109,8 +109,13 @@ function goto( mode)
%if settings.MITX_FEATURES.get('ENABLE_INSTRUCTOR_BETA_DASHBOARD'): - + %endif + %if studio_url: + ## not checking access because if user can see this, they are at least course staff (with studio edit access) + + %endif +

${_("Instructor Dashboard")}

@@ -125,7 +130,7 @@ function goto( mode) ${_("DataDump")} | ${_("Manage Groups")} %if show_email_tab: - | Email + | ${_("Email")} %endif %if settings.MITX_FEATURES.get('ENABLE_INSTRUCTOR_ANALYTICS'): | ${_("Analytics")}