diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py index b6ccfce2bb..2bc93fcf79 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -21,7 +21,7 @@ from xblock.fields import Scope from xblock.plugin import PluginMissingError from xblock.runtime import Mixologist -from contentstore.utils import get_lms_link_for_item, compute_publish_state +from contentstore.utils import get_lms_link_for_item, compute_publish_state, is_xblock_visible_to_students from contentstore.views.helpers import get_parent_xblock, is_unit, xblock_type_display_name from contentstore.views.item import create_xblock_info @@ -202,6 +202,7 @@ def container_handler(request, usage_key_string): 'xblock_locator': xblock.location, 'unit': unit, 'is_unit_page': is_unit_page, + 'is_visible_to_students': is_xblock_visible_to_students(xblock), 'subsection': subsection, 'section': section, 'new_unit_category': 'vertical', diff --git a/cms/djangoapps/contentstore/views/tests/test_container_page.py b/cms/djangoapps/contentstore/views/tests/test_container_page.py index b6f5cb5424..c7768d57b2 100644 --- a/cms/djangoapps/contentstore/views/tests/test_container_page.py +++ b/cms/djangoapps/contentstore/views/tests/test_container_page.py @@ -3,6 +3,8 @@ Unit tests for the container page. """ import re +import datetime +from pytz import UTC from contentstore.views.tests.utils import StudioPageTestCase from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.factories import ItemFactory @@ -25,6 +27,23 @@ class ContainerPageTestCase(StudioPageTestCase): self.video = self._create_item(self.child_vertical.location, "video", "My Video") self.store = modulestore() + past = datetime.datetime(1970, 1, 1, tzinfo=UTC) + future = datetime.datetime.now(UTC) + datetime.timedelta(days=1) + self.released_private_vertical = ItemFactory.create( + parent_location=self.sequential.location, category='vertical', display_name='Released Private Unit', + user_id=self.user.id, start=past) + self.unreleased_private_vertical = ItemFactory.create( + parent_location=self.sequential.location, category='vertical', display_name='Unreleased Private Unit', + user_id=self.user.id, start=future) + self.released_public_vertical = ItemFactory.create( + parent_location=self.sequential.location, category='vertical', display_name='Released Public Unit', + user_id=self.user.id, start=past) + self.unreleased_public_vertical = ItemFactory.create( + parent_location=self.sequential.location, category='vertical', display_name='Unreleased Public Unit', + user_id=self.user.id, start=future) + self.store.publish(self.unreleased_public_vertical.location, self.user.id) + self.store.publish(self.released_public_vertical.location, self.user.id) + def test_container_html(self): self._test_html_content( self.child_container, @@ -119,3 +138,39 @@ class ContainerPageTestCase(StudioPageTestCase): """ empty_child_container = self._create_item(self.vertical.location, 'split_test', 'Split Test') self.validate_preview_html(empty_child_container, self.reorderable_child_view, can_add=False) + + def test_unreleased_private_container_messages(self): + """ + Verify that an unreleased private container does not display messages. + """ + self.validate_html_for_messages(self.unreleased_private_vertical, False) + + def test_unreleased_public_container_messages(self): + """ + Verify that an unreleased public container does not display messages. + """ + self.validate_html_for_messages(self.unreleased_public_vertical, False) + + def test_released_private_container_message(self): + """ + Verify that a released private container does not display messages. + """ + self.validate_html_for_messages(self.released_private_vertical, False) + + def test_released_public_container_message(self): + """ + Verify that a released public container does display messages. + """ + self.validate_html_for_messages(self.released_public_vertical, True) + + def validate_html_for_messages(self, xblock, has_messages): + """ + Validate that the specified HTML has the appropriate messages for the current student visibility state. + """ + # Verify that there are no warning messages for blocks that are not visible to students + html = self.get_page_html(xblock) + messages_html = '
' + if has_messages: + self.assertIn(messages_html, html) + else: + self.assertNotIn(messages_html, html) diff --git a/cms/static/sass/elements/_system-feedback.scss b/cms/static/sass/elements/_system-feedback.scss index e1c0336c73..8a850b14b2 100644 --- a/cms/static/sass/elements/_system-feedback.scss +++ b/cms/static/sass/elements/_system-feedback.scss @@ -728,6 +728,70 @@ } } +// ==================== + +// block-level messages and validation +.wrapper-message { + + .message { + @extend %t-copy-sub1; + background-color: $gray-d2; + padding: ($baseline/2) ($baseline*.75); + color: $white; + + [class^="icon-"] { + font-style: normal; + } + + &.information { + @extend %t-copy-sub1; + background-color: $gray-l5; + color: $gray-d2; + } + + &.validation { + background-color: $gray-d2; + color: $white; + + a { + color: $blue-l2; + } + } + + &.has-warnings { + border-bottom: 3px solid $orange; + + .icon-warning-sign { + margin-right: ($baseline/2); + color: $orange; + } + } + + &.has-errors { + border-bottom: 3px solid $red-l2; + + .icon-exclamation-sign { + margin-right: ($baseline/2); + color: $red-l2; + } + } + } + + .message-list { + margin-bottom: 0; + } + + .message-actions { + padding: ($baseline/2) $baseline; + background-color: $gray-d1; + + .actions-list { + @extend %actions-list; + } + } +} + + // ==================== // temporary diff --git a/cms/static/sass/views/_container.scss b/cms/static/sass/views/_container.scss index ac1dccce5f..8c4df2b0aa 100644 --- a/cms/static/sass/views/_container.scss +++ b/cms/static/sass/views/_container.scss @@ -73,6 +73,13 @@ } } + .container-message { + + .message { + border-radius: 3px 3px 0 0; + } + } + // dragging bits .ui-sortable-helper { diff --git a/cms/templates/container.html b/cms/templates/container.html index c4d8f37893..24a67428b8 100644 --- a/cms/templates/container.html +++ b/cms/templates/container.html @@ -115,6 +115,16 @@ templates = ["basic-modal", "modal-button", "edit-xblock-modal",
+ % if is_visible_to_students: +
+
+

+ + ${_("This content is live for students. Edit with caution.")} +

+
+
+ % endif