Commit 720bde1d by Ibrahim Committed by Douglas Hall

add new text fields to schedule and details settings page

parent 31ca2a63
......@@ -245,6 +245,10 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
self.assertContains(response, "Introducing Your Course")
self.assertContains(response, "Course Image")
self.assertContains(response, "Course Short Description")
self.assertNotContains(response, "Course Title")
self.assertNotContains(response, "Course Subtitle")
self.assertNotContains(response, "Course Duration")
self.assertNotContains(response, "Course Description")
self.assertNotContains(response, "Course Overview")
self.assertNotContains(response, "Course Introduction Video")
self.assertNotContains(response, "Requirements")
......@@ -355,7 +359,8 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
def test_regular_site_fetch(self):
settings_details_url = get_url(self.course.id)
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': False}):
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': False,
'ENABLE_EXTENDED_COURSE_DETAILS': True}):
response = self.client.get_html(settings_details_url)
self.assertContains(response, "Course Summary Page")
self.assertContains(response, "Send a note to students via email")
......@@ -369,6 +374,10 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
self.assertContains(response, "Introducing Your Course")
self.assertContains(response, "Course Image")
self.assertContains(response, "Course Title")
self.assertContains(response, "Course Subtitle")
self.assertContains(response, "Course Duration")
self.assertContains(response, "Course Description")
self.assertContains(response, "Course Short Description")
self.assertContains(response, "Course Overview")
self.assertContains(response, "Course Introduction Video")
......
......@@ -976,11 +976,15 @@ def settings_handler(request, course_key_string):
'ENABLE_MKTG_SITE',
settings.FEATURES.get('ENABLE_MKTG_SITE', False)
)
enable_extended_course_details = microsite.get_value_for_org(
course_module.location.org,
'ENABLE_EXTENDED_COURSE_DETAILS',
settings.FEATURES.get('ENABLE_EXTENDED_COURSE_DETAILS', 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)
self_paced_enabled = SelfPacedConfiguration.current().enabled
settings_context = {
......@@ -1001,6 +1005,7 @@ def settings_handler(request, course_key_string):
'is_prerequisite_courses_enabled': is_prerequisite_courses_enabled(),
'is_entrance_exams_enabled': is_entrance_exams_enabled(),
'self_paced_enabled': self_paced_enabled,
'enable_extended_course_details': enable_extended_course_details
}
if is_prerequisite_courses_enabled():
courses, in_process_course_actions = get_courses_accessible_to_user(request)
......
......@@ -12,6 +12,10 @@ var CourseDetails = Backbone.Model.extend({
enrollment_start: null,
enrollment_end: null,
syllabus: null,
title: "",
subtitle: "",
duration: "",
description: "",
short_description: "",
overview: "",
intro_video: null,
......@@ -32,9 +36,30 @@ var CourseDetails = Backbone.Model.extend({
newattrs, ["start_date", "end_date", "enrollment_start", "enrollment_end"]
);
if (newattrs.title.length > 50) {
errors.title = gettext("The title field must be limited to 50 characters.");
}
if (newattrs.subtitle.length > 150) {
errors.subtitle = gettext("The subtitle field must be limited to 150 characters.");
}
if (newattrs.duration.length > 50) {
errors.duration = gettext("The duration field must be limited to 50 characters.");
}
if (newattrs.short_description.length > 150) {
errors.short_description = gettext("The short description field must be limited to 150 characters.");
}
if (newattrs.description.length > 1000) {
errors.description = gettext("The description field must be limited to 1000 characters.");
}
if (newattrs.start_date === null) {
errors.start_date = gettext("The course must have an assigned start date.");
}
if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) {
errors.end_date = gettext("The course end date must be later than the course start date.");
}
......
......@@ -21,6 +21,10 @@ define([
course_id : '',
run : '',
syllabus : null,
title: '',
subtitle: '',
duration: '',
description: '',
short_description : '',
overview : '',
intro_video : null,
......
......@@ -71,6 +71,16 @@ var DetailsView = ValidatingView.extend({
this.$el.find('#' + this.fieldToSelectorMap['overview']).val(this.model.get('overview'));
this.codeMirrorize(null, $('#course-overview')[0]);
if (this.model.get('title') !== '') {
this.$el.find('#' + this.fieldToSelectorMap.title).val(this.model.get('title'));
} else {
var displayName = this.$el.find('#' + this.fieldToSelectorMap.title).attr('data-display-name');
this.$el.find('#' + this.fieldToSelectorMap.title).val(displayName);
}
this.$el.find('#' + this.fieldToSelectorMap.subtitle).val(this.model.get('subtitle'));
this.$el.find('#' + this.fieldToSelectorMap.duration).val(this.model.get('duration'));
this.$el.find('#' + this.fieldToSelectorMap.description).val(this.model.get('description'));
this.$el.find('#' + this.fieldToSelectorMap['short_description']).val(this.model.get('short_description'));
this.$el.find('.current-course-introduction-video iframe').attr('src', this.model.videosourceSample());
......@@ -126,6 +136,10 @@ var DetailsView = ValidatingView.extend({
'enrollment_start' : 'enrollment-start',
'enrollment_end' : 'enrollment-end',
'overview' : 'course-overview',
'title': 'course-title',
'subtitle': 'course-subtitle',
'duration': 'course-duration',
'description': 'course-description',
'short_description' : 'course-short-description',
'intro_video' : 'course-introduction-video',
'effort' : "course-effort",
......@@ -194,9 +208,6 @@ var DetailsView = ValidatingView.extend({
updateModel: function(event) {
switch (event.currentTarget.id) {
case 'course-language':
this.setField(event);
break;
case 'course-image-url':
this.setField(event);
var url = $(event.currentTarget).val();
......@@ -208,9 +219,6 @@ var DetailsView = ValidatingView.extend({
$('#course-image').attr('src', $(event.currentTarget).val());
}, 1000);
break;
case 'course-effort':
this.setField(event);
break;
case 'entrance-exam-enabled':
if($(event.currentTarget).is(":checked")){
this.$('.div-grade-requirements').show();
......@@ -228,9 +236,6 @@ var DetailsView = ValidatingView.extend({
this.setField(event);
}
break;
case 'course-short-description':
this.setField(event);
break;
case 'pre-requisite-course':
var value = $(event.currentTarget).val();
value = value == "" ? [] : [value];
......@@ -257,6 +262,15 @@ var DetailsView = ValidatingView.extend({
case 'course-pace-instructor-paced':
this.model.set('self_paced', JSON.parse(event.currentTarget.value));
break;
case 'course-language':
case 'course-effort':
case 'course-title':
case 'course-subtitle':
case 'course-duration':
case 'course-description':
case 'course-short-description':
this.setField(event);
break;
default: // Everything else is handled by datepickers and CodeMirror.
break;
}
......
......@@ -27,7 +27,7 @@
<script type="text/javascript">
window.CMS = window.CMS || {};
CMS.URL = CMS.URL || {};
CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
CMS.URL.UPLOAD_ASSET = '${upload_asset_url}'
</script>
</%block>
......@@ -292,9 +292,33 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
<span class="tip">${_("Information for prospective students")}</span>
</header>
<ol class="list-input">
% if enable_extended_course_details:
<li class="field text" id="field-course-title">
<label for="course-title">${_("Course Title")}</label>
<input type="text" id="course-title" data-display-name="${context_course.display_name}">
<span class="tip tip-stacked">${_("Displayed as hero image overlay on the course details page. Limit to 50 characters.")}</span>
</li>
<li class="field text" id="field-course-subtitle">
<label for="course-subtitle">${_("Course Subtitle")}</label>
<input type="text" id="course-subtitle">
<span class="tip tip-stacked">${_("Displayed as hero image overlay on the course details page below the Course Title in a smaller font. Limit to 150 characters.")}</span>
</li>
<li class="field text" id="field-course-duration">
<label for="course-duration">${_("Course Duration")}</label>
<input type="text" id="course-duration">
<span class="tip tip-stacked">${_("Displayed on the course details page below the hero image. Limit to 50 characters.")}</span>
</li>
<li class="field text" id="field-course-description">
<label for="course-description">${_("Course Description")}</label>
<textarea class="text" id="course-description"></textarea>
<span class="tip tip-stacked">${_("Displayed on the course details page. Limit to 1000 characters.")}</span>
</li>
% endif
% if short_description_editable:
<li class="field text" id="field-course-short-description">
<label for="course-overview">${_("Course Short Description")}</label>
<label for="course-short-description">${_("Course Short Description")}</label>
<textarea class="text" id="course-short-description"></textarea>
<span class="tip tip-stacked">${_("Appears on the course catalog page when students roll over the course name. Limit to ~150 characters")}</span>
</li>
......@@ -315,7 +339,7 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
% endif
<li class="field image" id="field-course-image">
<label>${_("Course Image")}</label>
<label for="course-image-url">${_("Course Image")}</label>
<div class="current current-course-image">
% if context_course.course_image:
<span class="wrapper-course-image">
......@@ -346,7 +370,7 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
% if about_page_editable:
<li class="field video" id="field-course-introduction-video">
<label for="course-overview">${_("Course Introduction Video")}</label>
<label for="course-introduction-video">${_("Course Introduction Video")}</label>
<div class="input input-existing">
<div class="current current-course-introduction-video">
<iframe width="618" height="350" title="${_('Course Introduction Video')}" src="" frameborder="0" allowfullscreen></iframe>
......
......@@ -475,3 +475,36 @@ class ContentLicenseTest(StudioCourseTest):
# The course_license text will include a bunch of screen reader text to explain
# the selected options
self.assertIn("Some Rights Reserved", self.lms_courseware.course_license)
@attr('a11y')
class StudioSettingsA11yTest(StudioCourseTest):
"""
Class to test Studio pages accessibility.
"""
def setUp(self): # pylint: disable=arguments-differ
super(StudioSettingsA11yTest, self).setUp()
self.settings_page = SettingsPage(self.browser, self.course_info['org'], self.course_info['number'],
self.course_info['run'])
def test_studio_settings_page_a11y(self):
"""
Check accessibility of SettingsPage.
"""
self.settings_page.visit()
self.settings_page.wait_for_page()
# There are several existing color contrast errors on this page,
# we will ignore this error in the test until we fix them.
self.settings_page.a11y_audit.config.set_rules({
"ignore": [
'color-contrast', # TODO: AC-225
'link-href', # TODO: AC-226
'nav-aria-label', # TODO: AC-227
'icon-aria-hidden', # TODO: AC-229
],
})
self.settings_page.a11y_audit.check_for_accessibility_errors()
......@@ -18,6 +18,10 @@ from xmodule.modulestore.django import modulestore
# handled separately; its value maps to an alternate key name.
ABOUT_ATTRIBUTES = [
'syllabus',
'title',
'subtitle',
'duration',
'description',
'short_description',
'overview',
'effort',
......@@ -43,6 +47,10 @@ class CourseDetails(object):
self.enrollment_start = None
self.enrollment_end = None
self.syllabus = None # a pdf file asset
self.title = ""
self.subtitle = ""
self.duration = ""
self.description = ""
self.short_description = ""
self.overview = "" # html to render as the overview
self.intro_video = None # a video pointer
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment