Merge PR #24020 add/staff-toolbar-links
* Commits: Remove 'View In Studio' link from vertical Add Studio and Insights buttons to Instructor Toolbar
This commit is contained in:
@@ -1712,104 +1712,6 @@ class JsonInitDataTest(ModuleStoreTestCase):
|
||||
self.assertEqual(html.count("</script>"), 1)
|
||||
|
||||
|
||||
class ViewInStudioTest(ModuleStoreTestCase):
|
||||
"""Tests for the 'View in Studio' link visiblity."""
|
||||
|
||||
def setUp(self):
|
||||
""" Set up the user and request that will be used. """
|
||||
super(ViewInStudioTest, self).setUp()
|
||||
self.staff_user = GlobalStaffFactory.create()
|
||||
self.request = RequestFactoryNoCsrf().get('/')
|
||||
self.request.user = self.staff_user
|
||||
self.request.session = {}
|
||||
self.module = None
|
||||
self.default_context = {'bookmarked': False, 'username': self.user.username}
|
||||
|
||||
def _get_module(self, course_id, descriptor, location):
|
||||
"""
|
||||
Get the module from the course from which to pattern match (or not) the 'View in Studio' buttons
|
||||
"""
|
||||
field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
|
||||
course_id,
|
||||
self.staff_user,
|
||||
descriptor
|
||||
)
|
||||
|
||||
return render.get_module(
|
||||
self.staff_user,
|
||||
self.request,
|
||||
location,
|
||||
field_data_cache,
|
||||
)
|
||||
|
||||
def setup_mongo_course(self, course_edit_method='Studio'):
|
||||
""" Create a mongo backed course. """
|
||||
course = CourseFactory.create(
|
||||
course_edit_method=course_edit_method
|
||||
)
|
||||
|
||||
descriptor = ItemFactory.create(
|
||||
category='vertical',
|
||||
parent_location=course.location,
|
||||
)
|
||||
|
||||
child_descriptor = ItemFactory.create(
|
||||
category='vertical',
|
||||
parent_location=descriptor.location
|
||||
)
|
||||
|
||||
self.module = self._get_module(course.id, descriptor, descriptor.location)
|
||||
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
self.child_module = self._get_module(course.id, child_descriptor, child_descriptor.location)
|
||||
|
||||
|
||||
class MongoViewInStudioTest(ViewInStudioTest):
|
||||
"""Test the 'View in Studio' link visibility in a mongo backed course."""
|
||||
|
||||
def test_view_in_studio_link_studio_course(self):
|
||||
"""Regular Studio courses should see 'View in Studio' links."""
|
||||
self.setup_mongo_course()
|
||||
result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context)
|
||||
self.assertIn('View Unit in Studio', result_fragment.content)
|
||||
|
||||
def test_view_in_studio_link_only_in_top_level_vertical(self):
|
||||
"""Regular Studio courses should not see 'View in Studio' for child verticals of verticals."""
|
||||
self.setup_mongo_course()
|
||||
# Render the parent vertical, then check that there is only a single "View Unit in Studio" link.
|
||||
result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context)
|
||||
# The single "View Unit in Studio" link should appear before the first xmodule vertical definition.
|
||||
parts = result_fragment.content.split('data-block-type="vertical"')
|
||||
self.assertEqual(3, len(parts), "Did not find two vertical blocks")
|
||||
self.assertIn('View Unit in Studio', parts[0])
|
||||
self.assertNotIn('View Unit in Studio', parts[1])
|
||||
self.assertNotIn('View Unit in Studio', parts[2])
|
||||
|
||||
def test_view_in_studio_link_xml_authored(self):
|
||||
"""Courses that change 'course_edit_method' setting can hide 'View in Studio' links."""
|
||||
self.setup_mongo_course(course_edit_method='XML')
|
||||
result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context)
|
||||
self.assertNotIn('View Unit in Studio', result_fragment.content)
|
||||
|
||||
|
||||
class MixedViewInStudioTest(ViewInStudioTest):
|
||||
"""Test the 'View in Studio' link visibility in a mixed mongo backed course."""
|
||||
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def test_view_in_studio_link_mongo_backed(self):
|
||||
"""Mixed mongo courses that are mongo backed should see 'View in Studio' links."""
|
||||
self.setup_mongo_course()
|
||||
result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context)
|
||||
self.assertIn('View Unit in Studio', result_fragment.content)
|
||||
|
||||
def test_view_in_studio_link_xml_authored(self):
|
||||
"""Courses that change 'course_edit_method' setting can hide 'View in Studio' links."""
|
||||
self.setup_mongo_course(course_edit_method='XML')
|
||||
result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context)
|
||||
self.assertNotIn('View Unit in Studio', result_fragment.content)
|
||||
|
||||
|
||||
@XBlock.tag("detached")
|
||||
class DetachedXBlock(XBlock):
|
||||
"""
|
||||
|
||||
@@ -16,6 +16,10 @@ $proctoring-banner-text-size: 14px;
|
||||
@extend %inner-wrapper;
|
||||
|
||||
width: auto;
|
||||
|
||||
a.btn {
|
||||
margin: 5px 0 5px 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-actions {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<%page expression_filter="h"/>
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
|
||||
<div class="wrap-instructor-info studio-view">
|
||||
<a class="instructor-info-action" href="${edit_link}">${_("View Unit in Studio")}</a>
|
||||
</div>
|
||||
${frag_content | n, decode.utf8}
|
||||
@@ -26,10 +26,32 @@ show_preview_menu = course and can_masquerade and supports_preview_menu
|
||||
staff_selected = selected(not masquerade or masquerade.role != "student")
|
||||
specific_student_selected = selected(not staff_selected and masquerade.user_name)
|
||||
student_selected = selected(not staff_selected and not specific_student_selected and not masquerade_group_id)
|
||||
|
||||
if settings.HTTPS == 'on':
|
||||
protocol = 'https'
|
||||
else:
|
||||
protocol = 'http'
|
||||
insights_base_url = settings.ANALYTICS_DASHBOARD_URL
|
||||
studio_base_url = ''
|
||||
if settings.CMS_BASE:
|
||||
studio_base_url = protocol + '://' + settings.CMS_BASE
|
||||
insights_url = insights_base_url
|
||||
studio_url = studio_base_url
|
||||
if course and course.id:
|
||||
if insights_base_url:
|
||||
insights_url = "{base_url}/{course_id}".format(
|
||||
base_url=insights_base_url,
|
||||
course_id=course.id,
|
||||
)
|
||||
if studio_base_url:
|
||||
studio_url = "{base_url}/course/{course_id}".format(
|
||||
base_url=studio_base_url,
|
||||
course_id=course.id,
|
||||
)
|
||||
%>
|
||||
<nav class="wrapper-preview-menu" aria-label="${_('Course View')}">
|
||||
<div class="preview-menu" style="display: flex; align-items: center;">
|
||||
<ol class="preview-actions">
|
||||
<ol class="preview-actions" style="flex-grow: 1;">
|
||||
<li class="action-preview">
|
||||
<form action="#" class="action-preview-form" method="post">
|
||||
<label for="action-preview-select" class="action-preview-label">${_("View this course as:")}</label>
|
||||
@@ -66,13 +88,59 @@ show_preview_menu = course and can_masquerade and supports_preview_menu
|
||||
</p>
|
||||
</div>
|
||||
% endif
|
||||
<div style="flex-shrink: 1; text-align: center;">
|
||||
% if microfrontend_link:
|
||||
<div style="flex-grow: 1; text-align: right;">
|
||||
<a class="btn btn-primary" style="border: solid 1px white;" href="${microfrontend_link}">
|
||||
${_("View this unit in the new experience")}
|
||||
${_("View in the new experience")}
|
||||
</a>
|
||||
</div>
|
||||
% endif
|
||||
% if studio_url:
|
||||
<a
|
||||
class="btn btn-primary view-in-studio"
|
||||
style="border: solid 1px white;"
|
||||
href="${studio_url}"
|
||||
data-studio-base-url="${studio_base_url}"
|
||||
>
|
||||
${_("View in Studio")}
|
||||
</a>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$('.wrapper-preview-menu a.view-in-studio').click(function (event) {
|
||||
/*
|
||||
When we start rendering this template, we
|
||||
don't yet have a vertical in the context
|
||||
(that happens in a separate `render` call,
|
||||
if this is even on a unit-level page),
|
||||
so we dynamically lookup the vertical element in
|
||||
the DOM and use its data-* attributes to
|
||||
construct a Studio link directly to this unit.
|
||||
If no vertical is present, the link behaves as
|
||||
normal.
|
||||
*/
|
||||
var verticals = $('.xblock-student_view-vertical');
|
||||
if (verticals.length > 0) {
|
||||
var blockId = verticals[0].dataset.usageId;
|
||||
var url = [
|
||||
this.dataset.studioBaseUrl,
|
||||
'container',
|
||||
blockId,
|
||||
].join('/');
|
||||
window.location.href = url;
|
||||
return false;
|
||||
}
|
||||
// There's no vertical, so let the event
|
||||
// bubble up, ie, work like a normal link.
|
||||
return true;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
% endif
|
||||
% if insights_url:
|
||||
<a class="btn btn-primary" style="border: solid 1px white;" href="${insights_url}">
|
||||
${_("View in Insights")}
|
||||
</a>
|
||||
% endif
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
@@ -323,23 +323,7 @@ def add_staff_markup(user, disable_staff_debug_info, block, view, frag, context)
|
||||
return frag
|
||||
# TODO: make this more general, eg use an XModule attribute instead
|
||||
if isinstance(block, VerticalBlock) and (not context or not context.get('child_of_vertical', False)):
|
||||
# check that the course is a mongo backed Studio course before doing work
|
||||
is_studio_course = block.course_edit_method == "Studio"
|
||||
|
||||
if is_studio_course:
|
||||
# build edit link to unit in CMS. Can't use reverse here as lms doesn't load cms's urls.py
|
||||
edit_link = "//" + settings.CMS_BASE + '/container/' + text_type(block.location)
|
||||
|
||||
# return edit link in rendered HTML for display
|
||||
return wrap_fragment(
|
||||
frag,
|
||||
render_to_string(
|
||||
"edit_unit_link.html",
|
||||
{'frag_content': frag.content, 'edit_link': edit_link}
|
||||
)
|
||||
)
|
||||
else:
|
||||
return frag
|
||||
return frag
|
||||
|
||||
if isinstance(block, SequenceModule) or getattr(block, 'HIDDEN', False):
|
||||
return frag
|
||||
|
||||
Reference in New Issue
Block a user