Enable unit preview by default.
TNL-1261
This commit is contained in:
@@ -78,15 +78,16 @@ define(["jquery", "underscore", "underscore.string", "js/common_helpers/ajax_hel
|
||||
respondWithJson(json);
|
||||
};
|
||||
|
||||
describe("PreviewActionController", function () {
|
||||
describe("ViewLiveButtonController", function () {
|
||||
var viewPublishedCss = '.button-view',
|
||||
previewCss = '.button-preview',
|
||||
visibilityNoteCss = '.note-visibility';
|
||||
|
||||
it('renders correctly for unscheduled unit', function () {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
expect(containerPage.$(viewPublishedCss)).toHaveClass(disabledCss);
|
||||
expect(containerPage.$(previewCss)).not.toHaveClass(disabledCss);
|
||||
expect(containerPage.$(viewPublishedCss).attr('title')).toBe("Open the courseware in the LMS");
|
||||
expect(containerPage.$('.button-preview')).not.toHaveClass(disabledCss);
|
||||
expect(containerPage.$('.button-preview').attr('title')).toBe("Preview the courseware in the LMS");
|
||||
});
|
||||
|
||||
it('updates when publish state changes', function () {
|
||||
@@ -98,19 +99,6 @@ define(["jquery", "underscore", "underscore.string", "js/common_helpers/ajax_hel
|
||||
expect(containerPage.$(viewPublishedCss)).toHaveClass(disabledCss);
|
||||
});
|
||||
|
||||
it('updates when has_changes attribute changes', function () {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({has_changes: true});
|
||||
expect(containerPage.$(previewCss)).not.toHaveClass(disabledCss);
|
||||
|
||||
fetch({published: true, has_changes: false});
|
||||
expect(containerPage.$(previewCss)).toHaveClass(disabledCss);
|
||||
|
||||
// If published is false, preview is always enabled.
|
||||
fetch({published: false, has_changes: false});
|
||||
expect(containerPage.$(previewCss)).not.toHaveClass(disabledCss);
|
||||
});
|
||||
|
||||
it('updates when has_content_group_components attribute changes', function () {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({has_content_group_components: false});
|
||||
|
||||
@@ -68,11 +68,11 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
|
||||
});
|
||||
this.publishHistory.render();
|
||||
|
||||
this.previewActions = new ContainerSubviews.PreviewActionController({
|
||||
this.viewLiveActions = new ContainerSubviews.ViewLiveButtonController({
|
||||
el: this.$('.nav-actions'),
|
||||
model: this.model
|
||||
});
|
||||
this.previewActions.render();
|
||||
this.viewLiveActions.render();
|
||||
|
||||
this.unitOutlineView = new UnitOutlineView({
|
||||
el: this.$('.wrapper-unit-overview'),
|
||||
|
||||
@@ -50,28 +50,21 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
});
|
||||
|
||||
/**
|
||||
* A controller for updating the "View Live" and "Preview" buttons.
|
||||
* A controller for updating the "View Live" button.
|
||||
*/
|
||||
var PreviewActionController = ContainerStateListenerView.extend({
|
||||
var ViewLiveButtonController = ContainerStateListenerView.extend({
|
||||
shouldRefresh: function(model) {
|
||||
return ViewUtils.hasChangedAttributes(model, ['has_changes', 'published']);
|
||||
return ViewUtils.hasChangedAttributes(model, ['published']);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var previewAction = this.$el.find('.button-preview'),
|
||||
viewLiveAction = this.$el.find('.button-view');
|
||||
var viewLiveAction = this.$el.find('.button-view');
|
||||
if (this.model.get('published')) {
|
||||
viewLiveAction.removeClass(disabledCss).attr('aria-disabled', false);
|
||||
}
|
||||
else {
|
||||
viewLiveAction.addClass(disabledCss).attr('aria-disabled', true);
|
||||
}
|
||||
if (this.model.get('has_changes') || !this.model.get('published')) {
|
||||
previewAction.removeClass(disabledCss).attr('aria-disabled', false);
|
||||
}
|
||||
else {
|
||||
previewAction.addClass(disabledCss).attr('aria-disabled', true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -256,7 +249,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
|
||||
return {
|
||||
'MessageView': MessageView,
|
||||
'PreviewActionController': PreviewActionController,
|
||||
'ViewLiveButtonController': ViewLiveButtonController,
|
||||
'Publisher': Publisher,
|
||||
'PublishHistory': PublishHistory
|
||||
};
|
||||
|
||||
@@ -69,13 +69,13 @@ from django.utils.translation import ugettext as _
|
||||
<ul>
|
||||
% if is_unit_page:
|
||||
<li class="action-item action-view nav-item">
|
||||
<a href="${published_preview_link}" class="button button-view action-button is-disabled" aria-disabled="true" rel="external">
|
||||
<a href="${published_preview_link}" class="button button-view action-button is-disabled" aria-disabled="true" rel="external" title="${_('Open the courseware in the LMS')}">
|
||||
<span class="action-button-text">${_("View Live Version")}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="action-item action-preview nav-item">
|
||||
<a href="${draft_preview_link}" class="button button-preview action-button is-disabled" aria-disabled="true" rel="external">
|
||||
<span class="action-button-text">${_("Preview Changes")}</span>
|
||||
<a href="${draft_preview_link}" class="button button-preview action-button" rel="external" title="${_('Preview the courseware in the LMS')}">
|
||||
<span class="action-button-text">${_("Preview")}</span>
|
||||
</a>
|
||||
</li>
|
||||
% else:
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
<ul>
|
||||
% if is_unit_page:
|
||||
<li class="action-item action-view nav-item">
|
||||
<a href="${published_preview_link}" class="button button-view action-button is-disabled" aria-disabled="true">
|
||||
<a href="${published_preview_link}" class="button button-view action-button is-disabled" aria-disabled="true" title="Open the courseware in the LMS">
|
||||
<span class="action-button-text">View Live Version</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="action-item action-preview nav-item">
|
||||
<a href="${draft_preview_link}" class="button button-preview action-button is-disabled" aria-disabled="true">
|
||||
<span class="action-button-text">Preview Changes</span>
|
||||
<a href="${draft_preview_link}" class="button button-preview action-button" title="Preview the courseware in the LMS">
|
||||
<span class="action-button-text">Preview</span>
|
||||
</a>
|
||||
</li>
|
||||
% else:
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
</li>
|
||||
<li class="action-item action-preview nav-item">
|
||||
<a href="#" class="button preview-button action-button">
|
||||
<span class="action-button-text">Preview Changes</span>
|
||||
<span class="action-button-text">Preview</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- end publishing changes -->
|
||||
|
||||
@@ -209,7 +209,7 @@ class ContainerPage(PageObject):
|
||||
|
||||
def preview(self):
|
||||
"""
|
||||
Clicks "Preview Changes", which will open the draft version of the unit page in the LMS.
|
||||
Clicks "Preview", which will open the draft version of the unit page in the LMS.
|
||||
|
||||
Switches the browser to the newly opened LMS window.
|
||||
"""
|
||||
|
||||
@@ -22,6 +22,7 @@ from xmodule.error_module import ErrorDescriptor
|
||||
from xmodule.x_module import XModule, DEPRECATION_VSCOMPAT_EVENT
|
||||
from xmodule.split_test_module import get_split_user_partitions
|
||||
from xmodule.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPartitionGroupError
|
||||
from xmodule.util.django import get_current_request_hostname
|
||||
|
||||
from external_auth.models import ExternalAuthMap
|
||||
from courseware.masquerade import get_masquerade_role, is_masquerading_as_student
|
||||
@@ -436,7 +437,7 @@ def _has_access_descriptor(user, action, descriptor, course_key=None):
|
||||
descriptor,
|
||||
course_key=course_key
|
||||
)
|
||||
if now > effective_start:
|
||||
if in_preview_mode() or now > effective_start:
|
||||
# after start date, everyone can see it
|
||||
debug("Allow: now > effective start date")
|
||||
return True
|
||||
@@ -687,3 +688,11 @@ def get_user_role(user, course_key):
|
||||
return 'staff'
|
||||
else:
|
||||
return 'student'
|
||||
|
||||
|
||||
def in_preview_mode():
|
||||
"""
|
||||
Returns whether the user is in preview mode or not.
|
||||
"""
|
||||
hostname = get_current_request_hostname()
|
||||
return hostname and settings.PREVIEW_DOMAIN in hostname.split('.')
|
||||
|
||||
@@ -42,6 +42,16 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
self.course_staff = StaffFactory(course_key=self.course.course_key)
|
||||
self.course_instructor = InstructorFactory(course_key=self.course.course_key)
|
||||
|
||||
def verify_access(self, mock_unit, student_should_have_access):
|
||||
""" Verify the expected result from _has_access_descriptor """
|
||||
self.assertEqual(
|
||||
student_should_have_access,
|
||||
access._has_access_descriptor(self.anonymous_user, 'load', mock_unit, course_key=self.course.course_key)
|
||||
)
|
||||
self.assertTrue(
|
||||
access._has_access_descriptor(self.course_staff, 'load', mock_unit, course_key=self.course.course_key)
|
||||
)
|
||||
|
||||
def test_has_access_to_course(self):
|
||||
self.assertFalse(access._has_access_to_course(
|
||||
None, 'staff', self.course.course_key
|
||||
@@ -132,41 +142,73 @@ class AccessTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
mock_unit = Mock(user_partitions=[])
|
||||
mock_unit._class_tags = {} # Needed for detached check in _has_access_descriptor
|
||||
|
||||
def verify_access(student_should_have_access):
|
||||
""" Verify the expected result from _has_access_descriptor """
|
||||
self.assertEqual(student_should_have_access, access._has_access_descriptor(
|
||||
self.anonymous_user, 'load', mock_unit, course_key=self.course.course_key)
|
||||
)
|
||||
# staff always has access
|
||||
self.assertTrue(access._has_access_descriptor(
|
||||
self.course_staff, 'load', mock_unit, course_key=self.course.course_key)
|
||||
)
|
||||
|
||||
# No start date, staff lock on
|
||||
mock_unit.visible_to_staff_only = True
|
||||
verify_access(False)
|
||||
self.verify_access(mock_unit, False)
|
||||
|
||||
# No start date, staff lock off.
|
||||
mock_unit.visible_to_staff_only = False
|
||||
verify_access(True)
|
||||
self.verify_access(mock_unit, True)
|
||||
|
||||
# Start date in the past, staff lock on.
|
||||
mock_unit.start = datetime.datetime.now(pytz.utc) - datetime.timedelta(days=1)
|
||||
mock_unit.visible_to_staff_only = True
|
||||
verify_access(False)
|
||||
self.verify_access(mock_unit, False)
|
||||
|
||||
# Start date in the past, staff lock off.
|
||||
mock_unit.visible_to_staff_only = False
|
||||
verify_access(True)
|
||||
self.verify_access(mock_unit, True)
|
||||
|
||||
# Start date in the future, staff lock on.
|
||||
mock_unit.start = datetime.datetime.now(pytz.utc) + datetime.timedelta(days=1) # release date in the future
|
||||
mock_unit.visible_to_staff_only = True
|
||||
verify_access(False)
|
||||
self.verify_access(mock_unit, False)
|
||||
|
||||
# Start date in the future, staff lock off.
|
||||
mock_unit.visible_to_staff_only = False
|
||||
verify_access(False)
|
||||
self.verify_access(mock_unit, False)
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
|
||||
@patch('courseware.access.get_current_request_hostname', Mock(return_value='preview.localhost'))
|
||||
def test__has_access_descriptor_in_preview_mode(self):
|
||||
"""
|
||||
Tests that descriptor has access in preview mode.
|
||||
"""
|
||||
mock_unit = Mock(user_partitions=[])
|
||||
mock_unit._class_tags = {} # Needed for detached check in _has_access_descriptor
|
||||
|
||||
# No start date.
|
||||
mock_unit.visible_to_staff_only = False
|
||||
self.verify_access(mock_unit, True)
|
||||
|
||||
# Start date in the past.
|
||||
mock_unit.start = datetime.datetime.now(pytz.utc) - datetime.timedelta(days=1)
|
||||
self.verify_access(mock_unit, True)
|
||||
|
||||
# Start date in the future.
|
||||
mock_unit.start = datetime.datetime.now(pytz.utc) + datetime.timedelta(days=1) # release date in the future
|
||||
self.verify_access(mock_unit, True)
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
|
||||
@patch('courseware.access.get_current_request_hostname', Mock(return_value='localhost'))
|
||||
def test__has_access_descriptor_when_not_in_preview_mode(self):
|
||||
"""
|
||||
Tests that descriptor has no access when start date in future & without preview.
|
||||
"""
|
||||
mock_unit = Mock(user_partitions=[])
|
||||
mock_unit._class_tags = {} # Needed for detached check in _has_access_descriptor
|
||||
|
||||
# No start date.
|
||||
mock_unit.visible_to_staff_only = False
|
||||
self.verify_access(mock_unit, True)
|
||||
|
||||
# Start date in the past.
|
||||
mock_unit.start = datetime.datetime.now(pytz.utc) - datetime.timedelta(days=1)
|
||||
self.verify_access(mock_unit, True)
|
||||
|
||||
# Start date in the future.
|
||||
mock_unit.start = datetime.datetime.now(pytz.utc) + datetime.timedelta(days=1) # release date in the future
|
||||
self.verify_access(mock_unit, False)
|
||||
|
||||
def test__has_access_course_desc_can_enroll(self):
|
||||
yesterday = datetime.datetime.now(pytz.utc) - datetime.timedelta(days=1)
|
||||
|
||||
@@ -31,7 +31,7 @@ from django.db import transaction
|
||||
from markupsafe import escape
|
||||
|
||||
from courseware import grades
|
||||
from courseware.access import has_access, _adjust_start_date_for_beta_testers
|
||||
from courseware.access import has_access, in_preview_mode, _adjust_start_date_for_beta_testers
|
||||
from courseware.courses import (
|
||||
get_courses, get_course,
|
||||
get_studio_url, get_course_with_access,
|
||||
@@ -427,7 +427,7 @@ def _index_bulk_op(request, course_key, chapter, section, position):
|
||||
|
||||
now = datetime.now(UTC())
|
||||
effective_start = _adjust_start_date_for_beta_testers(user, course, course_key)
|
||||
if staff_access and now < effective_start:
|
||||
if not in_preview_mode() and staff_access and now < effective_start:
|
||||
# Disable student view button if user is staff and
|
||||
# course is not yet visible to students.
|
||||
context['disable_student_access'] = True
|
||||
@@ -702,7 +702,7 @@ def course_info(request, course_id):
|
||||
|
||||
now = datetime.now(UTC())
|
||||
effective_start = _adjust_start_date_for_beta_testers(request.user, course, course_key)
|
||||
if staff_access and now < effective_start:
|
||||
if not in_preview_mode() and staff_access and now < effective_start:
|
||||
# Disable student view button if user is staff and
|
||||
# course is not yet visible to students.
|
||||
context['disable_student_access'] = True
|
||||
|
||||
@@ -2295,3 +2295,6 @@ PROFILE_IMAGE_DEFAULT_FILE_EXTENSION = 'png'
|
||||
PROFILE_IMAGE_SECRET_KEY = 'placeholder secret key'
|
||||
PROFILE_IMAGE_MAX_BYTES = 1024 * 1024
|
||||
PROFILE_IMAGE_MIN_BYTES = 100
|
||||
|
||||
# This is to check the domain in case of preview.
|
||||
PREVIEW_DOMAIN = 'preview'
|
||||
|
||||
Reference in New Issue
Block a user