diff --git a/cms/static/js/spec/views/group_configuration_spec.js b/cms/static/js/spec/views/group_configuration_spec.js index 29488b551b..9309e04656 100644 --- a/cms/static/js/spec/views/group_configuration_spec.js +++ b/cms/static/js/spec/views/group_configuration_spec.js @@ -857,7 +857,7 @@ define([ beforeEach(function() { TemplateHelpers.installTemplate('content-group-details', true); - this.model = new GroupModel({name: 'Content Group', id: 0}); + this.model = new GroupModel({name: 'Content Group', id: 0, courseOutlineUrl: "CourseOutlineUrl"}); var saveableModel = new GroupConfigurationModel({ name: 'Content Group Configuration', @@ -888,7 +888,7 @@ define([ it('should hide empty usage appropriately', function() { this.view.$('.hide-groups').click(); - assertHideEmptyUsages(this.view) + assertHideEmptyUsages(this.view); }); it('should show non-empty usage appropriately', function() { @@ -1001,7 +1001,7 @@ define([ 'content-group-editor', 'content-group-details' ], true); - this.model = new GroupModel({name: 'Content Group', id: 0}); + this.model = new GroupModel({name: 'Content Group', id: 0, courseOutlineUrl: 'CourseOutlineUrl'}); this.saveableModel = new GroupConfigurationModel({ name: 'Content Group Configuration', diff --git a/cms/static/js/spec/views/pages/group_configurations_spec.js b/cms/static/js/spec/views/pages/group_configurations_spec.js index 5b8d4257ec..52c531600c 100644 --- a/cms/static/js/spec/views/pages/group_configurations_spec.js +++ b/cms/static/js/spec/views/pages/group_configurations_spec.js @@ -16,7 +16,8 @@ define([ experimentsEnabled: true, experimentGroupConfigurations: new GroupConfigurationCollection({ id: 0, - name: 'Configuration 1' + name: 'Configuration 1', + courseOutlineUrl: "CourseOutlineUrl" }), contentGroupConfiguration: new GroupConfigurationModel({groups: []}) }); diff --git a/cms/static/js/views/content_group_details.js b/cms/static/js/views/content_group_details.js index 4b6ed76820..1a2891ac88 100644 --- a/cms/static/js/views/content_group_details.js +++ b/cms/static/js/views/content_group_details.js @@ -3,8 +3,9 @@ * It is expected to be backed by a Group model. */ define([ - 'js/views/baseview', 'underscore', 'gettext', 'underscore.string' -], function(BaseView, _, gettext, str) { + 'js/views/baseview', 'underscore', 'gettext', 'underscore.string', + 'edx-ui-toolkit/js/utils/string-utils', 'edx-ui-toolkit/js/utils/html-utils' +], function(BaseView, _, gettext, str, StringUtils, HtmlUtils) { 'use strict'; var ContentGroupDetailsView = BaseView.extend({ @@ -37,9 +38,10 @@ define([ render: function(showContentGroupUsages) { var attrs = $.extend({}, this.model.attributes, { usageCountMessage: this.getUsageCountTitle(), - outlineAnchorMessage: this.getOutlineAnchorMessage(), + courseOutlineUrl: this.model.collection.parents[0].outlineUrl, index: this.model.collection.indexOf(this.model), - showContentGroupUsages: showContentGroupUsages || false + showContentGroupUsages: showContentGroupUsages || false, + HtmlUtils: HtmlUtils }); this.$el.html(this.template(attrs)); return this; @@ -56,41 +58,23 @@ define([ }, getUsageCountTitle: function () { - var count = this.model.get('usage').length, message; + var count = this.model.get('usage').length; if (count === 0) { - message = gettext('Not in Use'); + return gettext('Not in Use'); } else { - message = ngettext( + /* globals ngettext */ + return StringUtils.interpolate(ngettext( /* Translators: 'count' is number of units that the group configuration is used in. */ - 'Used in %(count)s unit', 'Used in %(count)s units', + 'Used in {count} unit', 'Used in {count} units', count + ), + {count: count} ); } - - return interpolate(message, { count: count }, true); - }, - - getOutlineAnchorMessage: function () { - var message = _.escape(gettext( - /* - Translators: 'outlineAnchor' is an anchor pointing to - the course outline page. - */ - 'This content group is not in use. Add a content group to any unit from the %(outlineAnchor)s.' - )), - anchor = str.sprintf( - '%(text)s', - { - url: this.model.collection.parents[0].outlineUrl, - text: _.escape(gettext('Course Outline')) - } - ); - - return str.sprintf(message, {outlineAnchor: anchor}); } }); diff --git a/cms/static/js/views/content_group_editor.js b/cms/static/js/views/content_group_editor.js index f249287cbe..8be838ddcb 100644 --- a/cms/static/js/views/content_group_editor.js +++ b/cms/static/js/views/content_group_editor.js @@ -23,8 +23,8 @@ function(ListItemEditorView, _) { getTemplateOptions: function() { return { - id: this.model.escape('id'), - name: this.model.escape('name'), + id: this.model.get('id'), + name: this.model.get('name'), index: this.model.collection.indexOf(this.model), isNew: this.model.isNew(), usage: this.model.get('usage'), diff --git a/cms/static/js/views/experiment_group_edit.js b/cms/static/js/views/experiment_group_edit.js index 8e3dccea0f..649b080ce1 100644 --- a/cms/static/js/views/experiment_group_edit.js +++ b/cms/static/js/views/experiment_group_edit.js @@ -32,7 +32,7 @@ function(BaseView, _, str, gettext) { index = collection.indexOf(this.model); this.$el.html(this.template({ - name: this.model.escape('name'), + name: this.model.get('name'), allocation: this.getAllocation(), index: index, error: this.model.validationError diff --git a/cms/static/js/views/group_configuration_details.js b/cms/static/js/views/group_configuration_details.js index 24fc35dee2..258dba6010 100644 --- a/cms/static/js/views/group_configuration_details.js +++ b/cms/static/js/views/group_configuration_details.js @@ -3,9 +3,10 @@ * It is expected to be instantiated with a GroupConfiguration model. */ define([ - 'js/views/baseview', 'underscore', 'gettext', 'underscore.string' + 'js/views/baseview', 'underscore', 'gettext', 'underscore.string', + 'edx-ui-toolkit/js/utils/string-utils', 'edx-ui-toolkit/js/utils/html-utils' ], -function(BaseView, _, gettext, str) { +function(BaseView, _, gettext, str, StringUtils, HtmlUtils) { 'use strict'; var GroupConfigurationDetailsView = BaseView.extend({ tagName: 'div', @@ -26,7 +27,7 @@ function(BaseView, _, gettext, str) { }, initialize: function() { - this.template = _.template( + this.template = HtmlUtils.template( $('#group-configuration-details-tpl').text() ); this.listenTo(this.model, 'change', this.render); @@ -36,11 +37,10 @@ function(BaseView, _, gettext, str) { var attrs = $.extend({}, this.model.attributes, { groupsCountMessage: this.getGroupsCountTitle(), usageCountMessage: this.getUsageCountTitle(), - outlineAnchorMessage: this.getOutlineAnchorMessage(), + courseOutlineUrl: this.model.collection.outlineUrl, index: this.model.collection.indexOf(this.model) }); - - this.$el.html(this.template(attrs)); + HtmlUtils.setHtml(this.$el, this.template(attrs)); return this; }, @@ -61,54 +61,37 @@ function(BaseView, _, gettext, str) { getGroupsCountTitle: function () { var count = this.model.get('groups').length, + /* globals ngettext */ message = ngettext( /* Translators: 'count' is number of groups that the group configuration contains. */ - 'Contains %(count)s group', 'Contains %(count)s groups', + 'Contains {count} group', 'Contains {count} groups', count ); - return interpolate(message, { count: count }, true); + return StringUtils.interpolate(message, { count: count }); }, getUsageCountTitle: function () { - var count = this.model.get('usage').length, message; + var count = this.model.get('usage').length; if (count === 0) { - message = gettext('Not in Use'); + return gettext('Not in Use'); } else { - message = ngettext( + return StringUtils.interpolate(ngettext( + /* Translators: 'count' is number of units that the group configuration is used in. */ - 'Used in %(count)s unit', 'Used in %(count)s units', + 'Used in {count} unit', 'Used in {count} units', count + ), + {count: count} ); } - - return interpolate(message, { count: count }, true); - }, - - getOutlineAnchorMessage: function () { - var message = gettext( - /* - Translators: 'outlineAnchor' is an anchor pointing to - the course outline page. - */ - 'This Group Configuration is not in use. Start by adding a content experiment to any Unit via the %(outlineAnchor)s.' - ), - anchor = str.sprintf( - '%(text)s', - { - url: this.model.collection.outlineUrl, - text: gettext('Course Outline') - } - ); - - return str.sprintf(message, {outlineAnchor: anchor}); } }); diff --git a/cms/static/js/views/group_configuration_editor.js b/cms/static/js/views/group_configuration_editor.js index 77df7112bd..33a1ddfba7 100644 --- a/cms/static/js/views/group_configuration_editor.js +++ b/cms/static/js/views/group_configuration_editor.js @@ -51,8 +51,8 @@ function(ListItemEditorView, _, $, gettext, ExperimentGroupEditView) { return { id: this.model.get('id'), uniqueId: _.uniqueId(), - name: this.model.escape('name'), - description: this.model.escape('description'), + name: this.model.get('name'), + description: this.model.get('description'), usage: this.model.get('usage'), isNew: this.model.isNew() }; diff --git a/cms/templates/group_configurations.html b/cms/templates/group_configurations.html index 9bc00afbc9..4d505fd8e9 100644 --- a/cms/templates/group_configurations.html +++ b/cms/templates/group_configurations.html @@ -1,3 +1,4 @@ +<%page expression_filter="h"/> <%inherit file="base.html" /> <%def name="content_groups_help_token()"><% return "content_groups" %> <%def name="experiment_group_configurations_help_token()"><% return "group_configurations" %> @@ -8,6 +9,7 @@ from django.utils.translation import ugettext as _ from openedx.core.djangolib.js_utils import ( dump_js_escaped_json, js_escaped_string ) +from openedx.core.djangolib.markup import Text, HTML %> <%block name="title">${_("Group Configurations")} @@ -76,7 +78,7 @@ from openedx.core.djangolib.js_utils import (

${_("Content Groups")}

${_("If you have cohorts enabled in your course, you can use content groups to create cohort-specific courseware. In other words, you can customize the content that particular cohorts see in your course.")}

${_("Each content group that you create can be associated with one or more cohorts. In addition to course content that is intended for all students, you can designate some content as visible only to specified content groups. Only learners in the cohorts that are associated with the specified content groups see the additional content.")}

-

${_("Click {em_start}New content group{em_end} to add a new content group. To edit the name of a content group, hover over its box and click {em_start}Edit{em_end}. You can delete a content group only if it is not in use by a unit. To delete a content group, hover over its box and click the delete icon.").format(em_start="", em_end="")}

+

${Text(_("Click {em_start}New content group{em_end} to add a new content group. To edit the name of a content group, hover over its box and click {em_start}Edit{em_end}. You can delete a content group only if it is not in use by a unit. To delete a content group, hover over its box and click the delete icon.")).format(em_start=HTML(""), em_end=HTML(""))}

${_("Learn More")}

@@ -85,7 +87,7 @@ from openedx.core.djangolib.js_utils import (

${_("Experiment Group Configurations")}

${_("Use experiment group configurations if you are conducting content experiments, also known as A/B testing, in your course. Experiment group configurations define how many groups of students are in a content experiment. When you create a content experiment for a course, you select the group configuration to use.")}

-

${_("Click {em_start}New Group Configuration{em_end} to add a new configuration. To edit a configuration, hover over its box and click {em_start}Edit{em_end}. You can delete a group configuration only if it is not in use in an experiment. To delete a configuration, hover over its box and click the delete icon.").format(em_start="", em_end="")}

+

${Text(_("Click {em_start}New Group Configuration{em_end} to add a new configuration. To edit a configuration, hover over its box and click {em_start}Edit{em_end}. You can delete a group configuration only if it is not in use in an experiment. To delete a configuration, hover over its box and click the delete icon.")).format(em_start=HTML(""), em_end=HTML(""))}

${_("Learn More")}

diff --git a/cms/templates/js/content-group-details.underscore b/cms/templates/js/content-group-details.underscore index 670fab89fb..7169c8dd51 100644 --- a/cms/templates/js/content-group-details.underscore +++ b/cms/templates/js/content-group-details.underscore @@ -51,9 +51,16 @@ <% } else { %>

- - <%= outlineAnchorMessage %> + <%= HtmlUtils.interpolateHtml( + gettext('This content group is not in use. Add a content group to any unit from the {linkStart}Course Outline{linkEnd}.'), + { + linkStart: HtmlUtils.interpolateHtml( + HtmlUtils.HTML(''), + {courseOutlineUrl: courseOutlineUrl, courseOutlineTitle: gettext('Course Outline')}), + linkEnd: HtmlUtils.HTML('') + }) + %>

<% } %> -<% } %> +<% } %> \ No newline at end of file diff --git a/cms/templates/js/content-group-editor.underscore b/cms/templates/js/content-group-editor.underscore index 0861e7b6ee..67924f98f3 100644 --- a/cms/templates/js/content-group-editor.underscore +++ b/cms/templates/js/content-group-editor.underscore @@ -1,44 +1,44 @@
<% if (error && error.message) { %>
- <%= gettext(error.message) %> + <%- gettext(error.message) %>
<% } %>
- <% + <% if (!_.isUndefined(id) && !_.isEmpty(id)) { %> - <%= gettext('Content Group ID') %> - <%= id %> + <%- gettext('Content Group ID') %> + <%- id %> <% } %> - "> + ">
<% if (!_.isEmpty(usage)) { %>

- <%= gettext('This content group is used in one or more units.') %> + <%- gettext('This content group is used in one or more units.') %>

<% } %>
- + <% if (!isNew) { %> <% if (_.isEmpty(usage)) { %> - "> - <%= gettext("Delete") %> + "> + <%- gettext("Delete") %> <% } else { %> - - <%= gettext("Delete") %> + + <%- gettext("Delete") %> <% } %> <% } %> diff --git a/cms/templates/js/group-configuration-details.underscore b/cms/templates/js/group-configuration-details.underscore index 4f5bc0374b..92c8657563 100644 --- a/cms/templates/js/group-configuration-details.underscore +++ b/cms/templates/js/group-configuration-details.underscore @@ -80,8 +80,15 @@ <% } else { %>

- - <%= outlineAnchorMessage %> + <%= HtmlUtils.interpolateHtml( + gettext('This Group Configuration is not in use. Start by adding a content experiment to any Unit via the {linkStart}Course Outline{linkEnd}.'), + { + linkStart: HtmlUtils.interpolateHtml( + HtmlUtils.HTML(''), + { courseOutlineUrl: courseOutlineUrl, courseOutlineTitle: gettext('Course Outline')}), + linkEnd: HtmlUtils.HTML('') + }) + %>

<% } %>
diff --git a/cms/templates/js/group-configuration-editor.underscore b/cms/templates/js/group-configuration-editor.underscore index 6ae85db9a7..cc58364fda 100644 --- a/cms/templates/js/group-configuration-editor.underscore +++ b/cms/templates/js/group-configuration-editor.underscore @@ -1,57 +1,57 @@ <% if (error && error.message) { %>
- <%= gettext(error.message) %> + <%- gettext(error.message) %>
<% } %>
- <%= gettext("Group Configuration information") %> + <%- gettext("Group Configuration information") %>
- <% + <% if (!_.isUndefined(id)) { %> - <%= gettext('Group Configuration ID') %> - <%= id %> + <%- gettext('Group Configuration ID') %> + <%- id %> <% } %> - " value="<%= name %>"> - <%= gettext("Name or short description of the configuration") %> + " value="<%- name %>"> + <%- gettext("Name or short description of the configuration") %>
- - - <%= gettext("Optional long description") %> + + + <%- gettext("Optional long description") %>
- <%= gettext("Group information") %> - - <%= gettext("Name of the groups that students will be assigned to, for example, Control, Video, Problems. You must have two or more groups.") %> + <%- gettext("Group information") %> + + <%- gettext("Name of the groups that students will be assigned to, for example, Control, Video, Problems. You must have two or more groups.") %>
    - +
    <% if (!_.isEmpty(usage)) { %>

    - <%= gettext('This configuration is currently used in content experiments. If you make changes to the groups, you may need to edit those experiments.') %> + <%- gettext('This configuration is currently used in content experiments. If you make changes to the groups, you may need to edit those experiments.') %>

    <% } %>
    - + <% if (!isNew) { %> <% if (_.isEmpty(usage)) { %> - <%= gettext("Delete") %> + <%- gettext("Delete") %> <% } else { %> - - <%= gettext("Delete") %> + + <%- gettext("Delete") %> <% } %> <% } %> diff --git a/cms/templates/js/group-edit.underscore b/cms/templates/js/group-edit.underscore index 7088793125..4fd5e31ae9 100644 --- a/cms/templates/js/group-edit.underscore +++ b/cms/templates/js/group-edit.underscore @@ -1,4 +1,4 @@ -
    -
    <%= allocation %>%
    - <%= gettext("delete group") %> +
    +
    <%- allocation %>%
    + <%- gettext("delete group") %> diff --git a/cms/templates/js/list.underscore b/cms/templates/js/list.underscore index c1314e0930..9ba9f647c0 100644 --- a/cms/templates/js/list.underscore +++ b/cms/templates/js/list.underscore @@ -3,7 +3,7 @@

    <%- emptyMessage %> - <%= interpolate( + <%- interpolate( gettext("%(new_item_message)s"), {new_item_message: newItemMessage}, true ) %>

    diff --git a/lms/static/js/groups/views/cohort_discussions_course_wide.js b/lms/static/js/groups/views/cohort_discussions_course_wide.js index 6237b78f9f..0873be734b 100644 --- a/lms/static/js/groups/views/cohort_discussions_course_wide.js +++ b/lms/static/js/groups/views/cohort_discussions_course_wide.js @@ -1,7 +1,8 @@ ;(function (define) { 'use strict'; - define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/views/cohort_discussions'], - function ($, _, Backbone, gettext, CohortDiscussionConfigurationView) { + define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/views/cohort_discussions', + 'edx-ui-toolkit/js/utils/html-utils'], + function ($, _, Backbone, gettext, CohortDiscussionConfigurationView, HtmlUtils) { var CourseWideDiscussionsView = CohortDiscussionConfigurationView.extend({ events: { 'change .check-discussion-subcategory-course-wide': 'discussionCategoryStateChanged', @@ -9,13 +10,13 @@ }, initialize: function (options) { - this.template = _.template($('#cohort-discussions-course-wide-tpl').text()); + this.template = HtmlUtils.template($('#cohort-discussions-course-wide-tpl').text()); this.cohortSettings = options.cohortSettings; }, render: function () { - this.$('.cohort-course-wide-discussions-nav').html(this.template({ - courseWideTopics: this.getCourseWideDiscussionsHtml( + HtmlUtils.setHtml(this.$('.cohort-course-wide-discussions-nav'), this.template({ + courseWideTopicsHtml: this.getCourseWideDiscussionsHtml( this.model.get('course_wide_discussions') ) })); @@ -25,14 +26,14 @@ /** * Returns the html list for course-wide discussion topics. * @param {object} courseWideDiscussions - course-wide discussions object from server. - * @returns {Array} - HTML list for course-wide discussion topics. + * @returns {HtmlSnippet} - HTML list for course-wide discussion topics. */ getCourseWideDiscussionsHtml: function (courseWideDiscussions) { - var subCategoryTemplate = _.template($('#cohort-discussions-subcategory-tpl').html()), + var subCategoryTemplate = HtmlUtils.template($('#cohort-discussions-subcategory-tpl').html()), entries = courseWideDiscussions.entries, children = courseWideDiscussions.children; - return _.map(children, function (name) { + return HtmlUtils.joinHtml.apply(this, _.map(children, function (name) { var entry = entries[name]; return subCategoryTemplate({ name: name, @@ -40,7 +41,7 @@ is_cohorted: entry.is_cohorted, type: 'course-wide' }); - }).join(''); + })); }, /** diff --git a/lms/static/js/groups/views/cohort_discussions_inline.js b/lms/static/js/groups/views/cohort_discussions_inline.js index 88bfb838d0..ea55c733d5 100644 --- a/lms/static/js/groups/views/cohort_discussions_inline.js +++ b/lms/static/js/groups/views/cohort_discussions_inline.js @@ -1,7 +1,8 @@ ;(function (define) { 'use strict'; - define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/views/cohort_discussions', 'js/vendor/jquery.qubit'], - function ($, _, Backbone, gettext, CohortDiscussionConfigurationView) { + define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/views/cohort_discussions', + 'edx-ui-toolkit/js/utils/html-utils', 'js/vendor/jquery.qubit'], + function ($, _, Backbone, gettext, CohortDiscussionConfigurationView, HtmlUtils) { var InlineDiscussionsView = CohortDiscussionConfigurationView.extend({ events: { 'change .check-discussion-category': 'setSaveButton', @@ -12,15 +13,16 @@ }, initialize: function (options) { - this.template = _.template($('#cohort-discussions-inline-tpl').text()); + this.template = HtmlUtils.template($('#cohort-discussions-inline-tpl').text()); this.cohortSettings = options.cohortSettings; }, render: function () { - var alwaysCohortInlineDiscussions = this.cohortSettings.get('always_cohort_inline_discussions'); + var alwaysCohortInlineDiscussions = this.cohortSettings.get('always_cohort_inline_discussions'), + inline_discussions = this.model.get('inline_discussions'); - this.$('.cohort-inline-discussions-nav').html(this.template({ - inlineDiscussionTopics: this.getInlineDiscussionsHtml(this.model.get('inline_discussions')), + HtmlUtils.setHtml(this.$('.cohort-inline-discussions-nav'), this.template({ + inlineDiscussionTopicsHtml: this.getInlineDiscussionsHtml(inline_discussions), alwaysCohortInlineDiscussions:alwaysCohortInlineDiscussions })); @@ -36,35 +38,35 @@ /** * Generate html list for inline discussion topics. * @params {object} inlineDiscussions - inline discussions object from server. - * @returns {Array} - HTML for inline discussion topics. + * @returns {HtmlSnippet} - HTML for inline discussion topics. */ getInlineDiscussionsHtml: function (inlineDiscussions) { - var categoryTemplate = _.template($('#cohort-discussions-category-tpl').html()), - entryTemplate = _.template($('#cohort-discussions-subcategory-tpl').html()), + var categoryTemplate = HtmlUtils.template($('#cohort-discussions-category-tpl').html()), + entryTemplate = HtmlUtils.template($('#cohort-discussions-subcategory-tpl').html()), isCategoryCohorted = false, children = inlineDiscussions.children, entries = inlineDiscussions.entries, subcategories = inlineDiscussions.subcategories; - return _.map(children, function (name) { - var html = '', entry; + return HtmlUtils.joinHtml.apply(this, _.map(children, function (name) { + var htmlSnippet = '', entry; if (entries && _.has(entries, name)) { entry = entries[name]; - html = entryTemplate({ + htmlSnippet = entryTemplate({ name: name, id: entry.id, is_cohorted: entry.is_cohorted, type: 'inline' }); } else { // subcategory - html = categoryTemplate({ + htmlSnippet = categoryTemplate({ name: name, - entries: this.getInlineDiscussionsHtml(subcategories[name]), + entriesHtml: this.getInlineDiscussionsHtml(subcategories[name]), isCategoryCohorted: isCategoryCohorted }); } - return html; - }, this).join(''); + return htmlSnippet; + }, this)); }, /** diff --git a/lms/static/js/groups/views/cohort_form.js b/lms/static/js/groups/views/cohort_form.js index 3a4f755e15..3cf21631aa 100644 --- a/lms/static/js/groups/views/cohort_form.js +++ b/lms/static/js/groups/views/cohort_form.js @@ -1,8 +1,8 @@ ;(function (define) { 'use strict'; - define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/models/cohort', + define(['jquery', 'underscore', 'backbone', 'gettext', 'edx-ui-toolkit/js/utils/html-utils', 'js/models/notification', 'js/views/notification'], - function($, _, Backbone, gettext, CohortModel) { + function($, _, Backbone, gettext, HtmlUtils) { var CohortFormView = Backbone.View.extend({ events : { @@ -10,7 +10,7 @@ }, initialize: function(options) { - this.template = _.template($('#cohort-form-tpl').text()); + this.template = HtmlUtils.template($('#cohort-form-tpl').text()); this.contentGroups = options.contentGroups; this.context = options.context; }, @@ -32,7 +32,7 @@ }, render: function() { - this.$el.html(this.template({ + HtmlUtils.setHtml(this.$el, this.template({ cohort: this.model, isDefaultCohort: this.isDefault(this.model.get('name')), contentGroups: this.contentGroups, diff --git a/lms/static/js/groups/views/cohorts.js b/lms/static/js/groups/views/cohorts.js index da06366fc7..4ae304a15b 100644 --- a/lms/static/js/groups/views/cohorts.js +++ b/lms/static/js/groups/views/cohorts.js @@ -4,9 +4,10 @@ 'js/groups/views/cohort_editor', 'js/groups/views/cohort_form', 'js/groups/views/course_cohort_settings_notification', 'js/groups/views/cohort_discussions_inline', 'js/groups/views/cohort_discussions_course_wide', + 'edx-ui-toolkit/js/utils/html-utils', 'js/views/file_uploader', 'js/models/notification', 'js/views/notification', 'string_utils'], function($, _, Backbone, gettext, CohortModel, CohortEditorView, CohortFormView, - CourseCohortSettingsNotificationView, InlineDiscussionsView, CourseWideDiscussionsView) { + CourseCohortSettingsNotificationView, InlineDiscussionsView, CourseWideDiscussionsView, HtmlUtils) { var hiddenClass = 'is-hidden', disabledClass = 'is-disabled'; @@ -27,8 +28,8 @@ initialize: function(options) { var model = this.model; - this.template = _.template($('#cohorts-tpl').text()); - this.selectorTemplate = _.template($('#cohort-selector-tpl').text()); + this.template = HtmlUtils.template($('#cohorts-tpl').text()); + this.selectorTemplate = HtmlUtils.template($('#cohort-selector-tpl').text()); this.context = options.context; this.contentGroups = options.contentGroups; this.cohortSettings = options.cohortSettings; @@ -43,7 +44,7 @@ }, render: function() { - this.$el.html(this.template({ + HtmlUtils.setHtml(this.$el, this.template({ cohorts: this.model.models, cohortsEnabled: this.cohortSettings.get('is_cohorted') })); @@ -52,7 +53,7 @@ }, renderSelector: function(selectedCohort) { - this.$('.cohort-select').html(this.selectorTemplate({ + HtmlUtils.setHtml(this.$('.cohort-select'), this.selectorTemplate({ cohorts: this.model.models, selectedCohort: selectedCohort })); diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-category.underscore b/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-category.underscore index 735f4f0ad6..6590b59a7c 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-category.underscore +++ b/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-category.underscore @@ -6,5 +6,5 @@
    - + diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-course-wide.underscore b/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-course-wide.underscore index 7cc647389f..5e71c1ea36 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-course-wide.underscore +++ b/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-course-wide.underscore @@ -7,7 +7,7 @@

    <%- gettext('Course-Wide Discussion Topics') %>

    <%- gettext('Select the course-wide discussion topics that you want to divide by cohort.') %>

    - +
    diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-inline.underscore b/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-inline.underscore index f70225d3d7..a51e5561e1 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-inline.underscore +++ b/lms/templates/instructor/instructor_dashboard_2/cohort-discussions-inline.underscore @@ -21,8 +21,8 @@
    - <% if ( inlineDiscussionTopics ) { %> - + <% if ( inlineDiscussionTopicsHtml.valueOf() ) { %> + <% } else { %> <%- gettext('No content-specific discussion topics exist.') %> <% } %> diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore b/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore index d206de5b7b..429afcfbaf 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore +++ b/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -93,14 +93,13 @@

    <%= - interpolate( - // Translators: Any text between %(screen_reader_start)s and %(screen_reader_end)s is only read by screen readers and never shown in the browser. - gettext('%(screen_reader_start)sWarning:%(screen_reader_end)s The previously selected content group was deleted. Select another content group.'), + HtmlUtils.interpolateHtml( + // Translators: Any text between {screen_reader_start} and {screen_reader_end} is only read by screen readers and never shown in the browser. + gettext('{screen_reader_start}Warning:{screen_reader_end} The previously selected content group was deleted. Select another content group.'), { - screen_reader_start: '', - screen_reader_end: '' - }, - true + screen_reader_start: HtmlUtils.HTML(''), + screen_reader_end: HtmlUtils.HTML('') + } ) %>

    @@ -113,14 +112,13 @@

    <%= - interpolate( - // Translators: Any text between %(screen_reader_start)s and %(screen_reader_end)s is only read by screen readers and never shown in the browser. - gettext('%(screen_reader_start)sWarning:%(screen_reader_end)s No content groups exist.'), + HtmlUtils.interpolateHtml( + // Translators: Any text between {screen_reader_start} and {screen_reader_end} is only read by screen readers and never shown in the browser. + gettext('{screen_reader_start}Warning:{screen_reader_end} No content groups exist.'), { - screen_reader_start: '', - screen_reader_end: '' - }, - true + screen_reader_start: HtmlUtils.HTML(''), + screen_reader_end: HtmlUtils.HTML('') + } ) %> <%- gettext("Create a content group") %> diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort-group-header.underscore b/lms/templates/instructor/instructor_dashboard_2/cohort-group-header.underscore index fd80117e47..027b0235e4 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort-group-header.underscore +++ b/lms/templates/instructor/instructor_dashboard_2/cohort-group-header.underscore @@ -12,7 +12,7 @@

    <% if (cohort.get('assignment_type') == "manual") { %> <%- gettext("Learners are added to this cohort only when you provide their email addresses or usernames on this page.") %> - <%= gettext("What does this mean?") %> + <%- gettext("What does this mean?") %> <% } else { %> <%- gettext("Learners are added to this cohort automatically.") %> <%- gettext("What does this mean?") %> diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort-selector.underscore b/lms/templates/instructor/instructor_dashboard_2/cohort-selector.underscore index e91c2d2c33..b5133f426b 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort-selector.underscore +++ b/lms/templates/instructor/instructor_dashboard_2/cohort-selector.underscore @@ -10,5 +10,5 @@ ); var isSelected = selectedCohort && selectedCohort.get('id') === cohort.get('id') %> - + <% }); %> diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort_management.html b/lms/templates/instructor/instructor_dashboard_2/cohort_management.html index 81fe4c4221..48452a570f 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort_management.html +++ b/lms/templates/instructor/instructor_dashboard_2/cohort_management.html @@ -1,8 +1,10 @@ +<%page expression_filter="h"/> + <%page args="section_data"/> <%namespace name='static' file='../../static_content.html'/> <%! from django.utils.translation import ugettext as _ -from openedx.core.djangolib.js_utils import js_escaped_string +from openedx.core.djangolib.js_utils import js_escaped_string, dump_js_escaped_json from courseware.courses import get_studio_url from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_user_partition %> @@ -23,17 +25,17 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_ cohorted_user_partition = get_cohorted_user_partition(course) content_groups = cohorted_user_partition.groups if cohorted_user_partition else [] %> - var cohortUserPartitionId = ${cohorted_user_partition.id if cohorted_user_partition else 'null'}, + var cohortUserPartitionId = ${cohorted_user_partition.id if cohorted_user_partition else None | n, dump_js_escaped_json}, contentGroups = [ % for content_group in content_groups: { - id: ${content_group.id}, + id: ${content_group.id | n, dump_js_escaped_json}, name: "${content_group.name | n, js_escaped_string}", user_partition_id: cohortUserPartitionId }, % endfor ]; - CohortsFactory(contentGroups, '${get_studio_url(course, 'group_configurations') | h}'); + CohortsFactory(contentGroups, "${get_studio_url(course, 'group_configurations') | n, js_escaped_string}");
    diff --git a/lms/templates/instructor/instructor_dashboard_2/cohorts.underscore b/lms/templates/instructor/instructor_dashboard_2/cohorts.underscore index 26925bb7d7..f6b6d6f993 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohorts.underscore +++ b/lms/templates/instructor/instructor_dashboard_2/cohorts.underscore @@ -40,11 +40,13 @@

    - <%= interpolate( - gettext('To review student cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on %(link_start)s the Data Download page. %(link_end)s'), - {link_start: '', link_end: ''}, - true - ) %> + <%= HtmlUtils.interpolateHtml( + gettext('To review student cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on {link_start} the Data Download page. {link_end}'), + { + link_start: HtmlUtils.HTML(''), + link_end: HtmlUtils.HTML('') + }) + %>