diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py
index a9dd9ee8bd..57a9718cf5 100644
--- a/cms/djangoapps/contentstore/tests/test_course_settings.py
+++ b/cms/djangoapps/contentstore/tests/test_course_settings.py
@@ -16,6 +16,9 @@ from models.settings.course_details import (CourseDetails, CourseSettingsEncoder
from models.settings.course_grading import CourseGradingModel
from contentstore.utils import reverse_course_url, reverse_usage_url
from xmodule.modulestore.tests.factories import CourseFactory
+from student.roles import CourseInstructorRole
+from student.tests.factories import UserFactory
+
from models.settings.course_metadata import CourseMetadata
from xmodule.fields import Date
@@ -1106,3 +1109,116 @@ class CourseGraderUpdatesTest(CourseTestCase):
self.assertEqual(obj, grader)
current_graders = CourseGradingModel.fetch(self.course.id).graders
self.assertEqual(len(self.starting_graders) + 1, len(current_graders))
+
+
+class CourseEnrollmentEndFieldTest(CourseTestCase):
+ """
+ Base class to test the enrollment end fields in the course settings details view in Studio
+ when using marketing site flag and global vs non-global staff to access the page.
+ """
+ NOT_EDITABLE_HELPER_MESSAGE = "Contact your edX Partner Manager to update these settings."
+ NOT_EDITABLE_DATE_WRAPPER = "
"
+ EDITABLE_DATE_FIELD = ""
+ EDITABLE_TIME_FIELD = ""
+
+ EDITABLE_ELEMENTS = [
+ EDITABLE_DATE_WRAPPER,
+ EDITABLE_TIME_WRAPPER,
+ EDITABLE_DATE_FIELD,
+ EDITABLE_TIME_FIELD,
+ ]
+
+ NOT_EDITABLE_ELEMENTS = [
+ NOT_EDITABLE_HELPER_MESSAGE,
+ NOT_EDITABLE_DATE_WRAPPER,
+ NOT_EDITABLE_TIME_WRAPPER,
+ NOT_EDITABLE_DATE_FIELD,
+ NOT_EDITABLE_TIME_FIELD,
+ ]
+
+ def setUp(self):
+ """ Initialize course used to test enrollment fields. """
+ super(CourseEnrollmentEndFieldTest, self).setUp()
+ self.course = CourseFactory.create(org='edX', number='dummy', display_name='Marketing Site Course')
+ self.course_details_url = reverse_course_url('settings_handler', unicode(self.course.id))
+
+ def _get_course_details_response(self, global_staff):
+ """ Return the course details page as either global or non-global staff"""
+ user = UserFactory(is_staff=global_staff)
+ CourseInstructorRole(self.course.id).add_users(user)
+
+ self.client.login(username=user.username, password='test')
+
+ return self.client.get_html(self.course_details_url)
+
+ def _verify_editable(self, response):
+ """ Verify that the response has expected editable fields.
+
+ Assert that all editable field content exists and no
+ uneditable field content exists for enrollment end fields.
+ """
+ self.assertEqual(response.status_code, 200)
+ for element in self.NOT_EDITABLE_ELEMENTS:
+ self.assertNotContains(response, element)
+
+ for element in self.EDITABLE_ELEMENTS:
+ self.assertContains(response, element)
+
+ def _verify_not_editable(self, response):
+ """ Verify that the response has expected non-editable fields.
+
+ Assert that all uneditable field content exists and no
+ editable field content exists for enrollment end fields.
+ """
+ self.assertEqual(response.status_code, 200)
+ for element in self.NOT_EDITABLE_ELEMENTS:
+ self.assertContains(response, element)
+
+ for element in self.EDITABLE_ELEMENTS:
+ self.assertNotContains(response, element)
+
+ @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_MKTG_SITE': False})
+ def test_course_details_with_disabled_setting_global_staff(self):
+ """ Test that user enrollment end date is editable in response.
+
+ Feature flag 'ENABLE_MKTG_SITE' is not enabled.
+ User is global staff.
+ """
+ self._verify_editable(self._get_course_details_response(True))
+
+ @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_MKTG_SITE': False})
+ def test_course_details_with_disabled_setting_non_global_staff(self):
+ """ Test that user enrollment end date is editable in response.
+
+ Feature flag 'ENABLE_MKTG_SITE' is not enabled.
+ User is non-global staff.
+ """
+ self._verify_editable(self._get_course_details_response(False))
+
+ @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_MKTG_SITE': True})
+ def test_course_details_with_enabled_setting_global_staff(self):
+ """ Test that user enrollment end date is editable in response.
+
+ Feature flag 'ENABLE_MKTG_SITE' is enabled.
+ User is global staff.
+ """
+ self._verify_editable(self._get_course_details_response(True))
+
+ @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_MKTG_SITE': True})
+ def test_course_details_with_enabled_setting_non_global_staff(self):
+ """ Test that user enrollment end date is not editable in response.
+
+ Feature flag 'ENABLE_MKTG_SITE' is enabled.
+ User is non-global staff.
+ """
+ self._verify_not_editable(self._get_course_details_response(False))
diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py
index 5c230c13d7..113a543ee4 100644
--- a/cms/djangoapps/contentstore/views/course.py
+++ b/cms/djangoapps/contentstore/views/course.py
@@ -903,12 +903,15 @@ def settings_handler(request, course_key_string):
# see if the ORG of this course can be attributed to a 'Microsite'. In that case, the
# course about page should be editable in Studio
- about_page_editable = not microsite.get_value_for_org(
+ marketing_site_enabled = microsite.get_value_for_org(
course_module.location.org,
'ENABLE_MKTG_SITE',
settings.FEATURES.get('ENABLE_MKTG_SITE', False)
)
+ about_page_editable = not marketing_site_enabled
+ enrollment_end_editable = GlobalStaff().has_user(request.user) or not marketing_site_enabled
+
short_description_editable = settings.FEATURES.get('EDITABLE_SHORT_DESCRIPTION', True)
settings_context = {
'context_course': course_module,
@@ -924,6 +927,7 @@ def settings_handler(request, course_key_string):
'credit_eligibility_enabled': credit_eligibility_enabled,
'is_credit_course': False,
'show_min_grade_warning': False,
+ 'enrollment_end_editable': enrollment_end_editable,
}
if prerequisite_course_enabled:
courses, in_process_course_actions = get_courses_accessible_to_user(request)
diff --git a/cms/static/sass/views/_settings.scss b/cms/static/sass/views/_settings.scss
index 822be9f2ba..8be7e82dd5 100644
--- a/cms/static/sass/views/_settings.scss
+++ b/cms/static/sass/views/_settings.scss
@@ -62,6 +62,27 @@
margin-top: ($baseline);
}
+ // specific fields - settings details
+ .settings-details {
+
+ // course details that should appear more like content than elements to change
+ .is-not-editable {
+
+ label {
+
+ }
+
+ input, textarea {
+ @extend %t-copy-lead1;
+ @extend %t-strong;
+ box-shadow: none;
+ border: none;
+ background: none;
+ margin: 0;
+ }
+ }
+ }
+
// in form - elements
.group-settings {
@@ -305,21 +326,10 @@
}
}
- // course details that should appear more like content than elements to change
- .field.is-not-editable {
-
- label {
-
- }
+ .is-not-editable {
input, textarea {
- @extend %t-copy-lead1;
- @extend %t-strong;
- box-shadow: none;
- border: none;
- background: none;
padding: 0;
- margin: 0;
}
}
@@ -438,6 +448,13 @@
padding-bottom: 0;
}
+ .is-not-editable {
+
+ input, textarea {
+ padding: 10px;
+ }
+ }
+
.field {
@include float(left);
width: flex-grid(3, 9);
diff --git a/cms/templates/settings.html b/cms/templates/settings.html
index 4f0769e080..9cccd92ecb 100644
--- a/cms/templates/settings.html
+++ b/cms/templates/settings.html
@@ -220,17 +220,25 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
${_("(UTC)")}
-
+ <%
+ enrollment_end_readonly = "readonly aria-readonly=\"true\"" if not enrollment_end_editable else ""
+ enrollment_end_editable_class = "is-not-editable" if not enrollment_end_editable else ""
+ %>
-
+
-
- ${_("Last day students can enroll")}
+
+
+ ${_("Last day students can enroll.")}
+ % if not enrollment_end_editable:
+ ${_("Contact your edX Partner Manager to update these settings.")}
+ % endif
+