Support making drafts of nested xblocks
This commit is contained in:
@@ -194,30 +194,30 @@ def course_image_url(course):
|
||||
return path
|
||||
|
||||
|
||||
class UnitState(object):
|
||||
class PublishState(object):
|
||||
draft = 'draft'
|
||||
private = 'private'
|
||||
public = 'public'
|
||||
|
||||
|
||||
def compute_unit_state(unit):
|
||||
def compute_publish_state(xblock):
|
||||
"""
|
||||
Returns whether this unit is 'draft', 'public', or 'private'.
|
||||
Returns whether this xblock is 'draft', 'public', or 'private'.
|
||||
|
||||
'draft' content is in the process of being edited, but still has a previous
|
||||
version visible in the LMS
|
||||
'public' content is locked and visible in the LMS
|
||||
'private' content is editabled and not visible in the LMS
|
||||
'private' content is editable and not visible in the LMS
|
||||
"""
|
||||
|
||||
if getattr(unit, 'is_draft', False):
|
||||
if getattr(xblock, 'is_draft', False):
|
||||
try:
|
||||
modulestore('direct').get_item(unit.location)
|
||||
return UnitState.draft
|
||||
modulestore('direct').get_item(xblock.location)
|
||||
return PublishState.draft
|
||||
except ItemNotFoundError:
|
||||
return UnitState.private
|
||||
return PublishState.private
|
||||
else:
|
||||
return UnitState.public
|
||||
return PublishState.public
|
||||
|
||||
|
||||
def add_extra_panel_tab(tab_type, course):
|
||||
|
||||
@@ -26,7 +26,7 @@ from xblock.runtime import Mixologist
|
||||
|
||||
from lms.lib.xblock.runtime import unquote_slashes
|
||||
|
||||
from contentstore.utils import get_lms_link_for_item, compute_unit_state, UnitState, get_modulestore
|
||||
from contentstore.utils import get_lms_link_for_item, compute_publish_state, PublishState, get_modulestore
|
||||
from contentstore.views.helpers import get_parent_xblock
|
||||
|
||||
from models.settings.course_grading import CourseGradingModel
|
||||
@@ -282,7 +282,7 @@ def unit_handler(request, tag=None, package_id=None, branch=None, version_guid=N
|
||||
),
|
||||
'section': containing_section,
|
||||
'new_unit_category': 'vertical',
|
||||
'unit_state': compute_unit_state(item),
|
||||
'unit_state': compute_publish_state(item),
|
||||
'published_date': (
|
||||
get_default_time_display(item.published_date)
|
||||
if item.published_date is not None else None
|
||||
|
||||
@@ -97,5 +97,5 @@ def xblock_studio_url(xblock, course=None):
|
||||
course_id = None
|
||||
if course:
|
||||
course_id = course.location.course_id
|
||||
locator = loc_mapper().translate_location(course_id, xblock.location)
|
||||
locator = loc_mapper().translate_location(course_id, xblock.location, published=False)
|
||||
return locator.url_reverse(prefix)
|
||||
|
||||
@@ -296,9 +296,9 @@ def _save_item(request, usage_loc, item_location, data=None, children=None, meta
|
||||
if publish == 'make_private':
|
||||
_xmodule_recurse(existing_item, lambda i: modulestore().unpublish(i.location))
|
||||
elif publish == 'create_draft':
|
||||
# This clones the existing item location to a draft location (the draft is
|
||||
# This recursively clones the existing item location to a draft location (the draft is
|
||||
# implicit, because modulestore is a Draft modulestore)
|
||||
modulestore().convert_to_draft(item_location)
|
||||
_xmodule_recurse(existing_item, lambda i: modulestore().convert_to_draft(i.location))
|
||||
|
||||
if data:
|
||||
# TODO Allow any scope.content fields not just "data" (exactly like the get below this)
|
||||
|
||||
@@ -15,6 +15,7 @@ from django.test.client import RequestFactory
|
||||
from contentstore.views.component import component_handler
|
||||
|
||||
from contentstore.tests.utils import CourseTestCase
|
||||
from contentstore.utils import compute_publish_state, PublishState
|
||||
from student.tests.factories import UserFactory
|
||||
from xmodule.capa_module import CapaDescriptor
|
||||
from xmodule.modulestore.django import modulestore
|
||||
@@ -647,6 +648,7 @@ class TestEditItem(ItemTest):
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
# Activate the editing view
|
||||
view_url = '/xblock/{locator}/studio_view'.format(locator=self.problem_locator)
|
||||
resp = self.client.get(view_url, HTTP_ACCEPT='application/json')
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
@@ -656,6 +658,50 @@ class TestEditItem(ItemTest):
|
||||
self.assertNotEqual(draft.data, published.data)
|
||||
|
||||
|
||||
def test_publish_states_of_nested_xblocks(self):
|
||||
""" Test publishing of a unit page containing a nested xblock """
|
||||
|
||||
resp = self.create_xblock(parent_locator=self.seq_locator, display_name='Test Unit', category='vertical')
|
||||
unit_locator = self.response_locator(resp)
|
||||
resp = self.create_xblock(parent_locator=unit_locator, category='wrapper')
|
||||
wrapper_locator = self.response_locator(resp)
|
||||
resp = self.create_xblock(parent_locator=wrapper_locator, category='html')
|
||||
html_locator = self.response_locator(resp)
|
||||
|
||||
# The unit and its children should be private initially
|
||||
unit_update_url = '/xblock/' + unit_locator
|
||||
unit = self.get_item_from_modulestore(unit_locator, True)
|
||||
html = self.get_item_from_modulestore(html_locator, True)
|
||||
self.assertEqual(compute_publish_state(unit), PublishState.private)
|
||||
self.assertEqual(compute_publish_state(html), PublishState.private)
|
||||
|
||||
# Make the unit public and verify that the problem is also made public
|
||||
resp = self.client.ajax_post(
|
||||
unit_update_url,
|
||||
data={'publish': 'make_public'}
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
unit = self.get_item_from_modulestore(unit_locator, True)
|
||||
html = self.get_item_from_modulestore(html_locator, True)
|
||||
self.assertEqual(compute_publish_state(unit), PublishState.public)
|
||||
self.assertEqual(compute_publish_state(html), PublishState.public)
|
||||
|
||||
# Make a draft for the unit and verify that the problem also has a draft
|
||||
resp = self.client.ajax_post(
|
||||
unit_update_url,
|
||||
data={
|
||||
'id': unit_locator,
|
||||
'metadata': {},
|
||||
'publish': 'create_draft'
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
unit = self.get_item_from_modulestore(unit_locator, True)
|
||||
html = self.get_item_from_modulestore(html_locator, True)
|
||||
self.assertEqual(compute_publish_state(unit), PublishState.draft)
|
||||
self.assertEqual(compute_publish_state(html), PublishState.draft)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestComponentHandler(TestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user