Studio support of Section Highlights
This commit is contained in:
@@ -1182,6 +1182,11 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
|
||||
xblock_info.update({
|
||||
'hide_after_due': xblock.hide_after_due,
|
||||
})
|
||||
elif xblock.category == 'chapter':
|
||||
xblock_info.update({
|
||||
'highlights': xblock.highlights,
|
||||
'highlights_enabled': settings.FEATURES.get('ENABLE_SECTION_HIGHLIGHTS', False),
|
||||
})
|
||||
|
||||
# update xblock_info with special exam information if the feature flag is enabled
|
||||
if settings.FEATURES.get('ENABLE_SPECIAL_EXAMS'):
|
||||
|
||||
@@ -264,7 +264,10 @@ FEATURES = {
|
||||
|
||||
# Whether archived courses (courses with end dates in the past) should be
|
||||
# shown in Studio in a separate list.
|
||||
'ENABLE_SEPARATE_ARCHIVED_COURSES': True
|
||||
'ENABLE_SEPARATE_ARCHIVED_COURSES': True,
|
||||
|
||||
# Whether section-level highlights are enabled on the platform.
|
||||
'ENABLE_SECTION_HIGHLIGHTS': False,
|
||||
}
|
||||
|
||||
ENABLE_JASMINE = False
|
||||
|
||||
@@ -326,6 +326,8 @@ SEARCH_ENGINE = "search.tests.mock_search_engine.MockSearchEngine"
|
||||
|
||||
FEATURES['ENABLE_ENROLLMENT_TRACK_USER_PARTITION'] = True
|
||||
|
||||
FEATURES['ENABLE_SECTION_HIGHLIGHTS'] = True
|
||||
|
||||
########################## AUTHOR PERMISSION #######################
|
||||
FEATURES['ENABLE_CREATOR_GROUP'] = False
|
||||
|
||||
|
||||
@@ -159,7 +159,12 @@ function(Backbone, _, str, ModuleUtils) {
|
||||
* some additional fields that are not stored in the course descriptor
|
||||
* (for example, which groups are selected for this particular XBlock).
|
||||
*/
|
||||
user_partitions: null
|
||||
user_partitions: null,
|
||||
/**
|
||||
* This xBlock's Highlights to message to learners.
|
||||
*/
|
||||
highlights: null,
|
||||
highlights_enabled: null
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
|
||||
@@ -197,6 +197,19 @@ define(['jquery', 'underscore', 'js/views/xblock_outline', 'common/js/components
|
||||
}
|
||||
},
|
||||
|
||||
highlightsXBlock: function() {
|
||||
var modal = CourseOutlineModalsFactory.getModal('highlights', this.model, {
|
||||
onSave: this.refresh.bind(this),
|
||||
xblockType: XBlockViewUtils.getXBlockType(
|
||||
this.model.get('category'), this.parentView.model, true
|
||||
)
|
||||
});
|
||||
|
||||
if (modal) {
|
||||
modal.show();
|
||||
}
|
||||
},
|
||||
|
||||
addButtonActions: function(element) {
|
||||
XBlockOutlineView.prototype.addButtonActions.apply(this, arguments);
|
||||
element.find('.configure-button').click(function(event) {
|
||||
@@ -207,6 +220,10 @@ define(['jquery', 'underscore', 'js/views/xblock_outline', 'common/js/components
|
||||
event.preventDefault();
|
||||
this.publishXBlock();
|
||||
}.bind(this));
|
||||
element.find('.highlights-button').click(function(event) {
|
||||
event.preventDefault();
|
||||
this.highlightsXBlock();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
makeContentDraggable: function(element) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* getTitle():
|
||||
* returns the title for the modal.
|
||||
* getHTMLContent():
|
||||
* getContentHtml():
|
||||
* returns the HTML content to be shown inside the modal.
|
||||
*
|
||||
* A modal implementation should also provide the following options:
|
||||
|
||||
@@ -13,10 +13,11 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
|
||||
$, Backbone, _, gettext, BaseView, BaseModal, date, XBlockViewUtils, DateUtils, HtmlUtils, StringUtils
|
||||
) {
|
||||
'use strict';
|
||||
var CourseOutlineXBlockModal, SettingsXBlockModal, PublishXBlockModal, AbstractEditor, BaseDateEditor,
|
||||
var CourseOutlineXBlockModal, SettingsXBlockModal, PublishXBlockModal, HighlightsXBlockModal,
|
||||
AbstractEditor, BaseDateEditor,
|
||||
ReleaseDateEditor, DueDateEditor, GradingEditor, PublishEditor, AbstractVisibilityEditor,
|
||||
StaffLockEditor, UnitAccessEditor, ContentVisibilityEditor, TimedExaminationPreferenceEditor,
|
||||
AccessEditor, ShowCorrectnessEditor;
|
||||
AccessEditor, ShowCorrectnessEditor, HighlightsEditor;
|
||||
|
||||
CourseOutlineXBlockModal = BaseModal.extend({
|
||||
events: _.extend({}, BaseModal.prototype.events, {
|
||||
@@ -206,6 +207,38 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
|
||||
}
|
||||
});
|
||||
|
||||
HighlightsXBlockModal = CourseOutlineXBlockModal.extend({
|
||||
initialize: function() {
|
||||
CourseOutlineXBlockModal.prototype.initialize.call(this);
|
||||
if (this.options.xblockType) {
|
||||
this.options.modalName = 'highlights-' + this.options.xblockType;
|
||||
}
|
||||
},
|
||||
|
||||
getTitle: function() {
|
||||
return StringUtils.interpolate(
|
||||
gettext('Highlights for {display_name}'),
|
||||
{display_name: this.model.get('display_name')}
|
||||
);
|
||||
},
|
||||
|
||||
getIntroductionMessage: function() {
|
||||
return StringUtils.interpolate(
|
||||
gettext(
|
||||
'The highlights you provide here are messaged (i.e., emailed) to learners. Each {item}\'s ' +
|
||||
'highlights are emailed at the time that we expect the learner to start working on that {item}. ' +
|
||||
'At this time, we assume that each {item} will take 1 week to complete.'
|
||||
),
|
||||
{item: this.options.xblockType}
|
||||
);
|
||||
},
|
||||
|
||||
addActionButtons: function() {
|
||||
this.addActionButton('save', gettext('Save'), true);
|
||||
this.addActionButton('cancel', gettext('Cancel'));
|
||||
}
|
||||
});
|
||||
|
||||
AbstractEditor = BaseView.extend({
|
||||
tagName: 'section',
|
||||
templateName: null,
|
||||
@@ -844,12 +877,58 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
|
||||
}
|
||||
});
|
||||
|
||||
HighlightsEditor = AbstractEditor.extend({
|
||||
templateName: 'highlights-editor',
|
||||
className: 'edit-show-highlights',
|
||||
|
||||
currentValue: function() {
|
||||
var highlights = [];
|
||||
$('.highlight-input-text').each(function() {
|
||||
var value = $(this).val();
|
||||
if (value !== '' && value !== null) {
|
||||
highlights.push(value);
|
||||
}
|
||||
});
|
||||
return highlights;
|
||||
},
|
||||
|
||||
hasChanges: function() {
|
||||
return this.model.get('highlights') !== this.currentValue();
|
||||
},
|
||||
|
||||
getRequestData: function() {
|
||||
if (this.hasChanges()) {
|
||||
return {
|
||||
publish: 'republish',
|
||||
metadata: {
|
||||
highlights: this.currentValue()
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
getContext: function() {
|
||||
return $.extend(
|
||||
{},
|
||||
AbstractEditor.prototype.getContext.call(this),
|
||||
{
|
||||
highlights: this.model.get('highlights') || []
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
getModal: function(type, xblockInfo, options) {
|
||||
if (type === 'edit') {
|
||||
return this.getEditModal(xblockInfo, options);
|
||||
} else if (type === 'publish') {
|
||||
return this.getPublishModal(xblockInfo, options);
|
||||
} else if (type === 'highlights') {
|
||||
return this.getHighlightsModal(xblockInfo, options);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -918,6 +997,13 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
|
||||
editors: [PublishEditor],
|
||||
model: xblockInfo
|
||||
}, options));
|
||||
},
|
||||
|
||||
getHighlightsModal: function(xblockInfo, options) {
|
||||
return new HighlightsXBlockModal($.extend({
|
||||
editors: [HighlightsEditor],
|
||||
model: xblockInfo
|
||||
}, options));
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -634,6 +634,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
// outline: highlight settings
|
||||
.highlights-button {
|
||||
cursor: pointer;
|
||||
color: $uxpl-blue-base;
|
||||
}
|
||||
|
||||
.highlight-input-text {
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.highlights-description {
|
||||
font-size: 80%;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
// outline: edit item settings
|
||||
.wrapper-modal-window-bulkpublish-section,
|
||||
.wrapper-modal-window-bulkpublish-subsection,
|
||||
|
||||
@@ -26,7 +26,7 @@ from openedx.core.djangolib.markup import HTML, Text
|
||||
|
||||
<%block name="header_extras">
|
||||
<link rel="stylesheet" type="text/css" href="${static.url('js/vendor/timepicker/jquery.timepicker.css')}" />
|
||||
% for template_name in ['course-outline', 'xblock-string-field-editor', 'basic-modal', 'modal-button', 'course-outline-modal', 'due-date-editor', 'release-date-editor', 'grading-editor', 'publish-editor', 'staff-lock-editor', 'unit-access-editor', 'content-visibility-editor', 'verification-access-editor', 'timed-examination-preference-editor', 'access-editor', 'settings-modal-tabs', 'show-correctness-editor']:
|
||||
% for template_name in ['course-outline', 'xblock-string-field-editor', 'basic-modal', 'modal-button', 'course-outline-modal', 'due-date-editor', 'release-date-editor', 'grading-editor', 'publish-editor', 'staff-lock-editor', 'unit-access-editor', 'content-visibility-editor', 'verification-access-editor', 'timed-examination-preference-editor', 'access-editor', 'settings-modal-tabs', 'show-correctness-editor', 'highlights-editor']:
|
||||
<script type="text/template" id="${template_name}-tpl">
|
||||
<%static:include path="js/${template_name}.underscore" />
|
||||
</script>
|
||||
|
||||
@@ -200,6 +200,22 @@ if (is_proctored_exam) {
|
||||
</p>
|
||||
</div>
|
||||
<% } %>
|
||||
<% if (xblockInfo.get('highlights_enabled') && course.get('self_paced') && xblockInfo.isChapter()) { %>
|
||||
<div class="block-highlights">
|
||||
<span class="sr block-highlights-label"><%- gettext('Highlights:') %></span>
|
||||
<% var number_of_highlights = (xblockInfo.get('highlights') || []).length; %>
|
||||
<% if (number_of_highlights > 0) { %>
|
||||
<span class="block-highlights-value highlights-button action-button">
|
||||
<%- edx.StringUtils.interpolate(
|
||||
gettext('Section Highlights: {number_of_highlights} entered'),
|
||||
{number_of_highlights: number_of_highlights}
|
||||
) %>
|
||||
</span>
|
||||
<% } else { %>
|
||||
<span class="block-highlights-value highlights-button action-button"><%- gettext('Enter Section Highlights') %></span>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } %>
|
||||
<% if (xblockInfo.get('is_time_limited')) { %>
|
||||
<div class="status-timed-proctored-exam">
|
||||
<p>
|
||||
|
||||
27
cms/templates/js/highlights-editor.underscore
Normal file
27
cms/templates/js/highlights-editor.underscore
Normal file
@@ -0,0 +1,27 @@
|
||||
<form>
|
||||
<h3 class="modal-section-title" id="highlights_label"><%- gettext('Section Highlights') %></h3>
|
||||
<div class="modal-section-content block-highlights">
|
||||
<div role="group" class="list-fields" aria-labelledby="highlights_label">
|
||||
<p class='field-message highlights-description' id='highlights_description'>
|
||||
<%- gettext('Please enter 3-5 highlights to be sent as separate bullet points in the message.') %>
|
||||
</p>
|
||||
<%
|
||||
var max_number_of_highlights = 5;
|
||||
%>
|
||||
<% _.each(highlights, function(highlight){ %>
|
||||
<input
|
||||
class="input input-text highlight-input-text"
|
||||
type="text" maxlength="250" aria-describedby="highlights_description"
|
||||
value="<%= _.escape(highlight) %>"
|
||||
/>
|
||||
<% }); %>
|
||||
<% for (i = highlights.length; i < max_number_of_highlights; i++) { %>
|
||||
<input
|
||||
class="input input-text highlight-input-text"
|
||||
type="text" maxlength="250" aria-describedby="highlights_description"
|
||||
placeholder="<%- gettext('A highlight to look forward to this week.') %>"
|
||||
/>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
Reference in New Issue
Block a user