diff --git a/lms/static/js/groups/collections/cohort.js b/lms/static/js/groups/collections/cohort.js index 12f524ce26..2f74cb69f7 100644 --- a/lms/static/js/groups/collections/cohort.js +++ b/lms/static/js/groups/collections/cohort.js @@ -1,16 +1,15 @@ -var edx = edx || {}; - -(function(Backbone, CohortModel) { +;(function (define) { 'use strict'; + define(['backbone', 'js/groups/models/cohort'], function(Backbone, CohortModel) { - edx.groups = edx.groups || {}; + var CohortCollection = Backbone.Collection.extend({ + model : CohortModel, + comparator: "name", - edx.groups.CohortCollection = Backbone.Collection.extend({ - model : CohortModel, - comparator: "name", - - parse: function(response) { - return response.cohorts; - } + parse: function(response) { + return response.cohorts; + } + }); + return CohortCollection; }); -}).call(this, Backbone, edx.groups.CohortModel); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/models/cohort.js b/lms/static/js/groups/models/cohort.js index e5d9a19144..933bf3ccab 100644 --- a/lms/static/js/groups/models/cohort.js +++ b/lms/static/js/groups/models/cohort.js @@ -1,29 +1,28 @@ -var edx = edx || {}; - -(function(Backbone) { +;(function (define) { 'use strict'; + define(['backbone'], function(Backbone) { - edx.groups = edx.groups || {}; - - edx.groups.CohortModel = Backbone.Model.extend({ - idAttribute: 'id', - defaults: { - name: '', - user_count: 0, - /** - * Indicates how students are added to the cohort. Will be "none" (signifying manual assignment) or - * "random" (indicating students are randomly assigned). - */ - assignment_type: '', - /** - * If this cohort is associated with a user partition group, the ID of the user partition. - */ - user_partition_id: null, - /** - * If this cohort is associated with a user partition group, the ID of the group within the - * partition associated with user_partition_id. - */ - group_id: null - } + var CohortModel = Backbone.Model.extend({ + idAttribute: 'id', + defaults: { + name: '', + user_count: 0, + /** + * Indicates how students are added to the cohort. Will be "none" (signifying manual assignment) or + * "random" (indicating students are randomly assigned). + */ + assignment_type: '', + /** + * If this cohort is associated with a user partition group, the ID of the user partition. + */ + user_partition_id: null, + /** + * If this cohort is associated with a user partition group, the ID of the group within the + * partition associated with user_partition_id. + */ + group_id: null + } + }); + return CohortModel; }); -}).call(this, Backbone); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/models/cohort_discussions.js b/lms/static/js/groups/models/cohort_discussions.js index 90af5a9207..b44d8513a7 100644 --- a/lms/static/js/groups/models/cohort_discussions.js +++ b/lms/static/js/groups/models/cohort_discussions.js @@ -1,14 +1,12 @@ -var edx = edx || {}; - -(function(Backbone) { +;(function (define) { 'use strict'; - - edx.groups = edx.groups || {}; - - edx.groups.DiscussionTopicsSettingsModel = Backbone.Model.extend({ - defaults: { - course_wide_discussions: {}, - inline_discussions: {} - } + define(['backbone'], function(Backbone) { + var DiscussionTopicsSettingsModel = Backbone.Model.extend({ + defaults: { + course_wide_discussions: {}, + inline_discussions: {} + } + }); + return DiscussionTopicsSettingsModel; }); -}).call(this, Backbone); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/models/content_group.js b/lms/static/js/groups/models/content_group.js index bb8077518e..313647ffd8 100644 --- a/lms/static/js/groups/models/content_group.js +++ b/lms/static/js/groups/models/content_group.js @@ -1,15 +1,13 @@ -var edx = edx || {}; - -(function(Backbone) { +;(function (define) { 'use strict'; - - edx.groups = edx.groups || {}; - - edx.groups.ContentGroupModel = Backbone.Model.extend({ - idAttribute: 'id', - defaults: { - name: '', - user_partition_id: null - } + define(['backbone'], function(Backbone) { + var ContentGroupModel = Backbone.Model.extend({ + idAttribute: 'id', + defaults: { + name: '', + user_partition_id: null + } + }); + return ContentGroupModel; }); -}).call(this, Backbone); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/models/course_cohort_settings.js b/lms/static/js/groups/models/course_cohort_settings.js index 74be792614..77dc6662cf 100644 --- a/lms/static/js/groups/models/course_cohort_settings.js +++ b/lms/static/js/groups/models/course_cohort_settings.js @@ -1,17 +1,16 @@ -var edx = edx || {}; - -(function(Backbone) { +;(function (define) { 'use strict'; + define(['backbone'], function(Backbone) { - edx.groups = edx.groups || {}; - - edx.groups.CourseCohortSettingsModel = Backbone.Model.extend({ - idAttribute: 'id', - defaults: { - is_cohorted: false, - cohorted_inline_discussions: [], - cohorted_course_wide_discussions:[], - always_cohort_inline_discussions: true - } + var CourseCohortSettingsModel = Backbone.Model.extend({ + idAttribute: 'id', + defaults: { + is_cohorted: false, + cohorted_inline_discussions: [], + cohorted_course_wide_discussions:[], + always_cohort_inline_discussions: true + } + }); + return CourseCohortSettingsModel; }); -}).call(this, Backbone); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/views/cohort_discussions.js b/lms/static/js/groups/views/cohort_discussions.js index b20c37d1f8..d0e8fed597 100644 --- a/lms/static/js/groups/views/cohort_discussions.js +++ b/lms/static/js/groups/views/cohort_discussions.js @@ -1,99 +1,98 @@ -var edx = edx || {}; - -(function ($, _, Backbone, gettext, interpolate_text, NotificationModel, NotificationView) { +;(function (define) { 'use strict'; + define(['jquery', 'underscore', 'backbone', 'gettext', 'js/models/notification', 'js/views/notification'], + function ($, _, Backbone) { - edx.groups = edx.groups || {}; + var CohortDiscussionConfigurationView = Backbone.View.extend({ - edx.groups.CohortDiscussionConfigurationView = Backbone.View.extend({ + /** + * Add/Remove the disabled attribute on given element. + * @param {object} $element - The element to disable/enable. + * @param {bool} disable - The flag to add/remove 'disabled' attribute. + */ + setDisabled: function($element, disable) { + $element.prop('disabled', disable ? 'disabled' : false); + }, - /** - * Add/Remove the disabled attribute on given element. - * @param {object} $element - The element to disable/enable. - * @param {bool} disable - The flag to add/remove 'disabled' attribute. - */ - setDisabled: function($element, disable) { - $element.prop('disabled', disable ? 'disabled' : false); - }, + /** + * Returns the cohorted discussions list. + * @param {string} selector - To select the discussion elements whose ids to return. + * @returns {Array} - Cohorted discussions. + */ + getCohortedDiscussions: function(selector) { + var self=this, + cohortedDiscussions = []; - /** - * Returns the cohorted discussions list. - * @param {string} selector - To select the discussion elements whose ids to return. - * @returns {Array} - Cohorted discussions. - */ - getCohortedDiscussions: function(selector) { - var self=this, - cohortedDiscussions = []; + _.each(self.$(selector), function (topic) { + cohortedDiscussions.push($(topic).data('id')) + }); + return cohortedDiscussions; + }, - _.each(self.$(selector), function (topic) { - cohortedDiscussions.push($(topic).data('id')) - }); - return cohortedDiscussions; - }, + /** + * Save the cohortSettings' changed attributes to the server via PATCH method. + * It shows the error message(s) if any. + * @param {object} $element - Messages would be shown before this element. + * @param {object} fieldData - Data to update on the server. + */ + saveForm: function ($element, fieldData) { + var self = this, + cohortSettingsModel = this.cohortSettings, + saveOperation = $.Deferred(), + showErrorMessage; - /** - * Save the cohortSettings' changed attributes to the server via PATCH method. - * It shows the error message(s) if any. - * @param {object} $element - Messages would be shown before this element. - * @param {object} fieldData - Data to update on the server. - */ - saveForm: function ($element, fieldData) { - var self = this, - cohortSettingsModel = this.cohortSettings, - saveOperation = $.Deferred(), - showErrorMessage; + showErrorMessage = function (message, $element) { + self.showMessage(message, $element, 'error'); + }; + this.removeNotification(); - showErrorMessage = function (message, $element) { - self.showMessage(message, $element, 'error'); - }; - this.removeNotification(); + cohortSettingsModel.save( + fieldData, {patch: true, wait: true} + ).done(function () { + saveOperation.resolve(); + }).fail(function (result) { + var errorMessage = null; + try { + var jsonResponse = JSON.parse(result.responseText); + errorMessage = jsonResponse.error; + } catch (e) { + // Ignore the exception and show the default error message instead. + } + if (!errorMessage) { + errorMessage = gettext("We've encountered an error. Refresh your browser and then try again."); + } + showErrorMessage(errorMessage, $element); + saveOperation.reject(); + }); + return saveOperation.promise(); + }, - cohortSettingsModel.save( - fieldData, {patch: true, wait: true} - ).done(function () { - saveOperation.resolve(); - }).fail(function (result) { - var errorMessage = null; - try { - var jsonResponse = JSON.parse(result.responseText); - errorMessage = jsonResponse.error; - } catch (e) { - // Ignore the exception and show the default error message instead. + /** + * Shows the notification messages before given element using the NotificationModel. + * @param {string} message - Text message to show. + * @param {object} $element - Message would be shown before this element. + * @param {string} type - Type of message to show e.g. confirmation or error. + */ + showMessage: function (message, $element, type) { + var model = new NotificationModel({type: type || 'confirmation', title: message}); + this.removeNotification(); + this.notification = new NotificationView({ + model: model + }); + $element.before(this.notification.$el); + this.notification.render(); + }, + + /** + *Removes the notification messages. + */ + removeNotification: function () { + if (this.notification) { + this.notification.remove(); + } } - if (!errorMessage) { - errorMessage = gettext("We've encountered an error. Refresh your browser and then try again."); - } - showErrorMessage(errorMessage, $element); - saveOperation.reject(); + }); - return saveOperation.promise(); - }, - - /** - * Shows the notification messages before given element using the NotificationModel. - * @param {string} message - Text message to show. - * @param {object} $element - Message would be shown before this element. - * @param {string} type - Type of message to show e.g. confirmation or error. - */ - showMessage: function (message, $element, type) { - var model = new NotificationModel({type: type || 'confirmation', title: message}); - this.removeNotification(); - this.notification = new NotificationView({ - model: model - }); - $element.before(this.notification.$el); - this.notification.render(); - }, - - /** - *Removes the notification messages. - */ - removeNotification: function () { - if (this.notification) { - this.notification.remove(); - } - } - - }); -}).call(this, $, _, Backbone, gettext, interpolate_text, NotificationModel, NotificationView -); + return CohortDiscussionConfigurationView; + }); +}).call(this, define || RequireJS.define); 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 97a06fea84..6237b78f9f 100644 --- a/lms/static/js/groups/views/cohort_discussions_course_wide.js +++ b/lms/static/js/groups/views/cohort_discussions_course_wide.js @@ -1,83 +1,82 @@ -var edx = edx || {}; - -(function ($, _, Backbone, gettext, interpolate_text, CohortDiscussionConfigurationView) { +;(function (define) { 'use strict'; + define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/views/cohort_discussions'], + function ($, _, Backbone, gettext, CohortDiscussionConfigurationView) { + var CourseWideDiscussionsView = CohortDiscussionConfigurationView.extend({ + events: { + 'change .check-discussion-subcategory-course-wide': 'discussionCategoryStateChanged', + 'click .cohort-course-wide-discussions-form .action-save': 'saveCourseWideDiscussionsForm' + }, - edx.groups = edx.groups || {}; + initialize: function (options) { + this.template = _.template($('#cohort-discussions-course-wide-tpl').text()); + this.cohortSettings = options.cohortSettings; + }, - edx.groups.CourseWideDiscussionsView = CohortDiscussionConfigurationView.extend({ - events: { - 'change .check-discussion-subcategory-course-wide': 'discussionCategoryStateChanged', - 'click .cohort-course-wide-discussions-form .action-save': 'saveCourseWideDiscussionsForm' - }, + render: function () { + this.$('.cohort-course-wide-discussions-nav').html(this.template({ + courseWideTopics: this.getCourseWideDiscussionsHtml( + this.model.get('course_wide_discussions') + ) + })); + this.setDisabled(this.$('.cohort-course-wide-discussions-form .action-save'), true); + }, - initialize: function (options) { - this.template = _.template($('#cohort-discussions-course-wide-tpl').text()); - this.cohortSettings = options.cohortSettings; - }, + /** + * 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. + */ + getCourseWideDiscussionsHtml: function (courseWideDiscussions) { + var subCategoryTemplate = _.template($('#cohort-discussions-subcategory-tpl').html()), + entries = courseWideDiscussions.entries, + children = courseWideDiscussions.children; - render: function () { - this.$('.cohort-course-wide-discussions-nav').html(this.template({ - courseWideTopics: this.getCourseWideDiscussionsHtml( - this.model.get('course_wide_discussions') - ) - })); - this.setDisabled(this.$('.cohort-course-wide-discussions-form .action-save'), true); - }, + return _.map(children, function (name) { + var entry = entries[name]; + return subCategoryTemplate({ + name: name, + id: entry.id, + is_cohorted: entry.is_cohorted, + type: 'course-wide' + }); + }).join(''); + }, - /** - * 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. - */ - getCourseWideDiscussionsHtml: function (courseWideDiscussions) { - var subCategoryTemplate = _.template($('#cohort-discussions-subcategory-tpl').html()), - entries = courseWideDiscussions.entries, - children = courseWideDiscussions.children; + /** + * Enables the save button for course-wide discussions. + */ + discussionCategoryStateChanged: function(event) { + event.preventDefault(); + this.setDisabled(this.$('.cohort-course-wide-discussions-form .action-save'), false); + }, + + /** + * Sends the cohorted_course_wide_discussions to the server and renders the view. + */ + saveCourseWideDiscussionsForm: function (event) { + event.preventDefault(); + + var self = this, + courseWideCohortedDiscussions = self.getCohortedDiscussions( + '.check-discussion-subcategory-course-wide:checked' + ), + fieldData = { cohorted_course_wide_discussions: courseWideCohortedDiscussions }; + + self.saveForm(self.$('.course-wide-discussion-topics'),fieldData) + .done(function () { + self.model.fetch() + .done(function () { + self.render(); + self.showMessage(gettext('Your changes have been saved.'), self.$('.course-wide-discussion-topics')); + }).fail(function() { + var errorMessage = gettext("We've encountered an error. Refresh your browser and then try again."); + self.showMessage(errorMessage, self.$('.course-wide-discussion-topics'), 'error') + }); + }); + } - return _.map(children, function (name) { - var entry = entries[name]; - return subCategoryTemplate({ - name: name, - id: entry.id, - is_cohorted: entry.is_cohorted, - type: 'course-wide' }); - }).join(''); - }, - - /** - * Enables the save button for course-wide discussions. - */ - discussionCategoryStateChanged: function(event) { - event.preventDefault(); - this.setDisabled(this.$('.cohort-course-wide-discussions-form .action-save'), false); - }, - - /** - * Sends the cohorted_course_wide_discussions to the server and renders the view. - */ - saveCourseWideDiscussionsForm: function (event) { - event.preventDefault(); - - var self = this, - courseWideCohortedDiscussions = self.getCohortedDiscussions( - '.check-discussion-subcategory-course-wide:checked' - ), - fieldData = { cohorted_course_wide_discussions: courseWideCohortedDiscussions }; - - self.saveForm(self.$('.course-wide-discussion-topics'),fieldData) - .done(function () { - self.model.fetch() - .done(function () { - self.render(); - self.showMessage(gettext('Your changes have been saved.'), self.$('.course-wide-discussion-topics')); - }).fail(function() { - var errorMessage = gettext("We've encountered an error. Refresh your browser and then try again."); - self.showMessage(errorMessage, self.$('.course-wide-discussion-topics'), 'error') - }); - }); - } - - }); -}).call(this, $, _, Backbone, gettext, interpolate_text, edx.groups.CohortDiscussionConfigurationView); + return CourseWideDiscussionsView; + }); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/views/cohort_discussions_inline.js b/lms/static/js/groups/views/cohort_discussions_inline.js index 036b2dafc6..88bfb838d0 100644 --- a/lms/static/js/groups/views/cohort_discussions_inline.js +++ b/lms/static/js/groups/views/cohort_discussions_inline.js @@ -1,145 +1,144 @@ -var edx = edx || {}; - -(function ($, _, Backbone, gettext, interpolate_text, CohortDiscussionConfigurationView) { +;(function (define) { 'use strict'; + define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/views/cohort_discussions', 'js/vendor/jquery.qubit'], + function ($, _, Backbone, gettext, CohortDiscussionConfigurationView) { + var InlineDiscussionsView = CohortDiscussionConfigurationView.extend({ + events: { + 'change .check-discussion-category': 'setSaveButton', + 'change .check-discussion-subcategory-inline': 'setSaveButton', + 'click .cohort-inline-discussions-form .action-save': 'saveInlineDiscussionsForm', + 'change .check-all-inline-discussions': 'setAllInlineDiscussions', + 'change .check-cohort-inline-discussions': 'setSomeInlineDiscussions' + }, - edx.groups = edx.groups || {}; + initialize: function (options) { + this.template = _.template($('#cohort-discussions-inline-tpl').text()); + this.cohortSettings = options.cohortSettings; + }, - edx.groups.InlineDiscussionsView = CohortDiscussionConfigurationView.extend({ - events: { - 'change .check-discussion-category': 'setSaveButton', - 'change .check-discussion-subcategory-inline': 'setSaveButton', - 'click .cohort-inline-discussions-form .action-save': 'saveInlineDiscussionsForm', - 'change .check-all-inline-discussions': 'setAllInlineDiscussions', - 'change .check-cohort-inline-discussions': 'setSomeInlineDiscussions' - }, + render: function () { + var alwaysCohortInlineDiscussions = this.cohortSettings.get('always_cohort_inline_discussions'); - initialize: function (options) { - this.template = _.template($('#cohort-discussions-inline-tpl').text()); - this.cohortSettings = options.cohortSettings; - }, + this.$('.cohort-inline-discussions-nav').html(this.template({ + inlineDiscussionTopics: this.getInlineDiscussionsHtml(this.model.get('inline_discussions')), + alwaysCohortInlineDiscussions:alwaysCohortInlineDiscussions + })); - render: function () { - var alwaysCohortInlineDiscussions = this.cohortSettings.get('always_cohort_inline_discussions'); + // Provides the semantics for a nested list of tri-state checkboxes. + // When attached to a jQuery element it listens for change events to + // input[type=checkbox] elements, and updates the checked and indeterminate + // based on the checked values of any checkboxes in child elements of the DOM. + this.$('ul.inline-topics').qubit(); - this.$('.cohort-inline-discussions-nav').html(this.template({ - inlineDiscussionTopics: this.getInlineDiscussionsHtml(this.model.get('inline_discussions')), - alwaysCohortInlineDiscussions:alwaysCohortInlineDiscussions - })); + this.setElementsEnabled(alwaysCohortInlineDiscussions, true); + }, - // Provides the semantics for a nested list of tri-state checkboxes. - // When attached to a jQuery element it listens for change events to - // input[type=checkbox] elements, and updates the checked and indeterminate - // based on the checked values of any checkboxes in child elements of the DOM. - this.$('ul.inline-topics').qubit(); + /** + * Generate html list for inline discussion topics. + * @params {object} inlineDiscussions - inline discussions object from server. + * @returns {Array} - HTML for inline discussion topics. + */ + getInlineDiscussionsHtml: function (inlineDiscussions) { + var categoryTemplate = _.template($('#cohort-discussions-category-tpl').html()), + entryTemplate = _.template($('#cohort-discussions-subcategory-tpl').html()), + isCategoryCohorted = false, + children = inlineDiscussions.children, + entries = inlineDiscussions.entries, + subcategories = inlineDiscussions.subcategories; - this.setElementsEnabled(alwaysCohortInlineDiscussions, true); - }, + return _.map(children, function (name) { + var html = '', entry; + if (entries && _.has(entries, name)) { + entry = entries[name]; + html = entryTemplate({ + name: name, + id: entry.id, + is_cohorted: entry.is_cohorted, + type: 'inline' + }); + } else { // subcategory + html = categoryTemplate({ + name: name, + entries: this.getInlineDiscussionsHtml(subcategories[name]), + isCategoryCohorted: isCategoryCohorted + }); + } + return html; + }, this).join(''); + }, - /** - * Generate html list for inline discussion topics. - * @params {object} inlineDiscussions - inline discussions object from server. - * @returns {Array} - HTML for inline discussion topics. - */ - getInlineDiscussionsHtml: function (inlineDiscussions) { - var categoryTemplate = _.template($('#cohort-discussions-category-tpl').html()), - entryTemplate = _.template($('#cohort-discussions-subcategory-tpl').html()), - isCategoryCohorted = false, - children = inlineDiscussions.children, - entries = inlineDiscussions.entries, - subcategories = inlineDiscussions.subcategories; + /** + * Enable/Disable the inline discussion elements. + * + * Disables the category and sub-category checkboxes. + * Enables the save button. + */ + setAllInlineDiscussions: function(event) { + event.preventDefault(); + this.setElementsEnabled(($(event.currentTarget).prop('checked')), false); + }, - return _.map(children, function (name) { - var html = '', entry; - if (entries && _.has(entries, name)) { - entry = entries[name]; - html = entryTemplate({ - name: name, - id: entry.id, - is_cohorted: entry.is_cohorted, - type: 'inline' - }); - } else { // subcategory - html = categoryTemplate({ - name: name, - entries: this.getInlineDiscussionsHtml(subcategories[name]), - isCategoryCohorted: isCategoryCohorted - }); - } - return html; - }, this).join(''); - }, + /** + * Enables the inline discussion elements. + * + * Enables the category and sub-category checkboxes. + * Enables the save button. + */ + setSomeInlineDiscussions: function(event) { + event.preventDefault(); + this.setElementsEnabled(!($(event.currentTarget).prop('checked')), false); + }, - /** - * Enable/Disable the inline discussion elements. - * - * Disables the category and sub-category checkboxes. - * Enables the save button. - */ - setAllInlineDiscussions: function(event) { - event.preventDefault(); - this.setElementsEnabled(($(event.currentTarget).prop('checked')), false); - }, + /** + * Enable/Disable the inline discussion elements. + * + * Enable/Disable the category and sub-category checkboxes. + * Enable/Disable the save button. + * @param {bool} enable_checkboxes - The flag to enable/disable the checkboxes. + * @param {bool} enable_save_button - The flag to enable/disable the save button. + */ + setElementsEnabled: function(enable_checkboxes, enable_save_button) { + this.setDisabled(this.$('.check-discussion-category'), enable_checkboxes); + this.setDisabled(this.$('.check-discussion-subcategory-inline'), enable_checkboxes); + this.setDisabled(this.$('.cohort-inline-discussions-form .action-save'), enable_save_button); + }, - /** - * Enables the inline discussion elements. - * - * Enables the category and sub-category checkboxes. - * Enables the save button. - */ - setSomeInlineDiscussions: function(event) { - event.preventDefault(); - this.setElementsEnabled(!($(event.currentTarget).prop('checked')), false); - }, + /** + * Enables the save button for inline discussions. + */ + setSaveButton: function(event) { + this.setDisabled(this.$('.cohort-inline-discussions-form .action-save'), false); + }, - /** - * Enable/Disable the inline discussion elements. - * - * Enable/Disable the category and sub-category checkboxes. - * Enable/Disable the save button. - * @param {bool} enable_checkboxes - The flag to enable/disable the checkboxes. - * @param {bool} enable_save_button - The flag to enable/disable the save button. - */ - setElementsEnabled: function(enable_checkboxes, enable_save_button) { - this.setDisabled(this.$('.check-discussion-category'), enable_checkboxes); - this.setDisabled(this.$('.check-discussion-subcategory-inline'), enable_checkboxes); - this.setDisabled(this.$('.cohort-inline-discussions-form .action-save'), enable_save_button); - }, + /** + * Sends the cohorted_inline_discussions to the server and renders the view. + */ + saveInlineDiscussionsForm: function (event) { + event.preventDefault(); - /** - * Enables the save button for inline discussions. - */ - setSaveButton: function(event) { - this.setDisabled(this.$('.cohort-inline-discussions-form .action-save'), false); - }, + var self = this, + cohortedInlineDiscussions = self.getCohortedDiscussions( + '.check-discussion-subcategory-inline:checked' + ), + fieldData= { + cohorted_inline_discussions: cohortedInlineDiscussions, + always_cohort_inline_discussions: self.$('.check-all-inline-discussions').prop('checked') + }; - /** - * Sends the cohorted_inline_discussions to the server and renders the view. - */ - saveInlineDiscussionsForm: function (event) { - event.preventDefault(); - - var self = this, - cohortedInlineDiscussions = self.getCohortedDiscussions( - '.check-discussion-subcategory-inline:checked' - ), - fieldData= { - cohorted_inline_discussions: cohortedInlineDiscussions, - always_cohort_inline_discussions: self.$('.check-all-inline-discussions').prop('checked') - }; - - self.saveForm(self.$('.inline-discussion-topics'), fieldData) - .done(function () { - self.model.fetch() - .done(function () { - self.render(); - self.showMessage(gettext('Your changes have been saved.'), self.$('.inline-discussion-topics')); - }).fail(function() { - var errorMessage = gettext("We've encountered an error. Refresh your browser and then try again."); - self.showMessage(errorMessage, self.$('.inline-discussion-topics'), 'error') - }); - }); - } + self.saveForm(self.$('.inline-discussion-topics'), fieldData) + .done(function () { + self.model.fetch() + .done(function () { + self.render(); + self.showMessage(gettext('Your changes have been saved.'), self.$('.inline-discussion-topics')); + }).fail(function() { + var errorMessage = gettext("We've encountered an error. Refresh your browser and then try again."); + self.showMessage(errorMessage, self.$('.inline-discussion-topics'), 'error') + }); + }); + } + }); + return InlineDiscussionsView; }); -}).call(this, $, _, Backbone, gettext, interpolate_text, edx.groups.CohortDiscussionConfigurationView); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/views/cohort_editor.js b/lms/static/js/groups/views/cohort_editor.js index 8795c9baf5..78763424f3 100644 --- a/lms/static/js/groups/views/cohort_editor.js +++ b/lms/static/js/groups/views/cohort_editor.js @@ -1,259 +1,258 @@ -var edx = edx || {}; - -(function(Backbone, _, $, gettext, ngettext, interpolate_text, CohortFormView, NotificationModel, NotificationView) { +;(function (define) { 'use strict'; + define(['backbone', 'underscore', 'jquery', 'gettext', 'js/groups/views/cohort_form', 'string_utils', + 'js/models/notification', 'js/views/notification'], + function(Backbone, _, $, gettext, CohortFormView) { + var CohortEditorView = Backbone.View.extend({ - edx.groups = edx.groups || {}; + events : { + 'click .wrapper-tabs .tab': 'selectTab', + 'click .tab-content-settings .action-save': 'saveSettings', + 'click .tab-content-settings .action-cancel': 'cancelSettings', + 'submit .cohort-management-group-add-form': 'addStudents' + }, - edx.groups.CohortEditorView = Backbone.View.extend({ + initialize: function(options) { + this.template = _.template($('#cohort-editor-tpl').text()); + this.groupHeaderTemplate = _.template($('#cohort-group-header-tpl').text()); + this.cohorts = options.cohorts; + this.contentGroups = options.contentGroups; + this.context = options.context; + }, - events : { - 'click .wrapper-tabs .tab': 'selectTab', - 'click .tab-content-settings .action-save': 'saveSettings', - 'click .tab-content-settings .action-cancel': 'cancelSettings', - 'submit .cohort-management-group-add-form': 'addStudents' - }, + // Any errors that are currently being displayed to the instructor (for example, unknown email addresses). + errorNotifications: null, + // Any confirmation messages that are currently being displayed (for example, number of students added). + confirmationNotifications: null, - initialize: function(options) { - this.template = _.template($('#cohort-editor-tpl').text()); - this.groupHeaderTemplate = _.template($('#cohort-group-header-tpl').text()); - this.cohorts = options.cohorts; - this.contentGroups = options.contentGroups; - this.context = options.context; - }, - - // Any errors that are currently being displayed to the instructor (for example, unknown email addresses). - errorNotifications: null, - // Any confirmation messages that are currently being displayed (for example, number of students added). - confirmationNotifications: null, - - render: function() { - this.$el.html(this.template({ - cohort: this.model - })); - this.renderGroupHeader(); - this.cohortFormView = new CohortFormView({ - model: this.model, - contentGroups: this.contentGroups, - context: this.context - }); - this.cohortFormView.render(); - this.$('.tab-content-settings').append(this.cohortFormView.$el); - return this; - }, - - renderGroupHeader: function() { - this.$('.cohort-management-group-header').html(this.groupHeaderTemplate({ - cohort: this.model - })); - }, - - selectTab: function(event) { - var tabElement = $(event.currentTarget), - tabName = tabElement.data('tab'); - event.preventDefault(); - this.$('.wrapper-tabs .tab').removeClass('is-selected'); - this.$('.wrapper-tabs .tab').find('span.sr').remove(); - tabElement.addClass('is-selected'); - tabElement.find('a').prepend('' + gettext('Selected tab') + ' '); - this.$('.tab-content').addClass('is-hidden'); - this.$('.tab-content-' + tabName).removeClass('is-hidden').focus(); - }, - - saveSettings: function(event) { - var cohortFormView = this.cohortFormView; - var self = this; - event.preventDefault(); - cohortFormView.saveForm() - .done(function() { - self.renderGroupHeader(); - cohortFormView.showMessage(gettext('Saved cohort')); - }); - }, - - cancelSettings: function(event) { - event.preventDefault(); - this.render(); - }, - - setCohort: function(cohort) { - this.model = cohort; - this.render(); - }, - - addStudents: function(event) { - event.preventDefault(); - var self = this, - cohorts = this.cohorts, - input = this.$('.cohort-management-group-add-students'), - add_url = this.model.url() + '/add', - students = input.val().trim(), - cohortId = this.model.id; - - if (students.length > 0) { - $.post( - add_url, {'users': students} - ).done(function(modifiedUsers) { - self.refreshCohorts().done(function() { - // Find the equivalent cohort in the new collection and select it - var cohort = cohorts.get(cohortId); - self.setCohort(cohort); - - // Show the notifications - self.addNotifications(modifiedUsers); - - // If an unknown user was specified then update the new input to have - // the original input's value. This is to allow the user to correct the - // value in case it was a typo. - if (modifiedUsers.unknown.length > 0) { - self.$('.cohort-management-group-add-students').val(students); - } + render: function() { + this.$el.html(this.template({ + cohort: this.model + })); + this.renderGroupHeader(); + this.cohortFormView = new CohortFormView({ + model: this.model, + contentGroups: this.contentGroups, + context: this.context }); - }).fail(function() { - self.showErrorMessage(gettext('Error adding students.'), true); - }); - } else { - self.showErrorMessage(gettext('Enter a username or email.'), true); - input.val(''); - } - }, + this.cohortFormView.render(); + this.$('.tab-content-settings').append(this.cohortFormView.$el); + return this; + }, - /** - * Refresh the cohort collection to get the latest set as well as up-to-date counts. - */ - refreshCohorts: function() { - return this.cohorts.fetch(); - }, + renderGroupHeader: function() { + this.$('.cohort-management-group-header').html(this.groupHeaderTemplate({ + cohort: this.model + })); + }, - undelegateViewEvents: function (view) { - if (view) { - view.undelegateEvents(); - } - }, + selectTab: function(event) { + var tabElement = $(event.currentTarget), + tabName = tabElement.data('tab'); + event.preventDefault(); + this.$('.wrapper-tabs .tab').removeClass('is-selected'); + this.$('.wrapper-tabs .tab').find('span.sr').remove(); + tabElement.addClass('is-selected'); + tabElement.find('a').prepend('' + gettext('Selected tab') + ' '); + this.$('.tab-content').addClass('is-hidden'); + this.$('.tab-content-' + tabName).removeClass('is-hidden').focus(); + }, - showErrorMessage: function(message, removeConfirmations, model) { - if (removeConfirmations && this.confirmationNotifications) { - this.undelegateViewEvents(this.confirmationNotifications); - this.confirmationNotifications.$el.html(''); - this.confirmationNotifications = null; - } - if (model === undefined) { - model = new NotificationModel(); - } - model.set('type', 'error'); - model.set('title', message); + saveSettings: function(event) { + var cohortFormView = this.cohortFormView; + var self = this; + event.preventDefault(); + cohortFormView.saveForm() + .done(function() { + self.renderGroupHeader(); + cohortFormView.showMessage(gettext('Saved cohort')); + }); + }, - this.undelegateViewEvents(this.errorNotifications); + cancelSettings: function(event) { + event.preventDefault(); + this.render(); + }, - this.errorNotifications = new NotificationView({ - el: this.$('.cohort-errors'), - model: model + setCohort: function(cohort) { + this.model = cohort; + this.render(); + }, + + addStudents: function(event) { + event.preventDefault(); + var self = this, + cohorts = this.cohorts, + input = this.$('.cohort-management-group-add-students'), + add_url = this.model.url() + '/add', + students = input.val().trim(), + cohortId = this.model.id; + + if (students.length > 0) { + $.post( + add_url, {'users': students} + ).done(function(modifiedUsers) { + self.refreshCohorts().done(function() { + // Find the equivalent cohort in the new collection and select it + var cohort = cohorts.get(cohortId); + self.setCohort(cohort); + + // Show the notifications + self.addNotifications(modifiedUsers); + + // If an unknown user was specified then update the new input to have + // the original input's value. This is to allow the user to correct the + // value in case it was a typo. + if (modifiedUsers.unknown.length > 0) { + self.$('.cohort-management-group-add-students').val(students); + } + }); + }).fail(function() { + self.showErrorMessage(gettext('Error adding students.'), true); + }); + } else { + self.showErrorMessage(gettext('Enter a username or email.'), true); + input.val(''); + } + }, + + /** + * Refresh the cohort collection to get the latest set as well as up-to-date counts. + */ + refreshCohorts: function() { + return this.cohorts.fetch(); + }, + + undelegateViewEvents: function (view) { + if (view) { + view.undelegateEvents(); + } + }, + + showErrorMessage: function(message, removeConfirmations, model) { + if (removeConfirmations && this.confirmationNotifications) { + this.undelegateViewEvents(this.confirmationNotifications); + this.confirmationNotifications.$el.html(''); + this.confirmationNotifications = null; + } + if (model === undefined) { + model = new NotificationModel(); + } + model.set('type', 'error'); + model.set('title', message); + + this.undelegateViewEvents(this.errorNotifications); + + this.errorNotifications = new NotificationView({ + el: this.$('.cohort-errors'), + model: model + }); + this.errorNotifications.render(); + }, + + addNotifications: function(modifiedUsers) { + var oldCohort, title, details, numPresent, numUsersAdded, numErrors, + createErrorDetails, errorActionCallback, errorModel, + errorLimit = 5; + + // Show confirmation messages. + this.undelegateViewEvents(this.confirmationNotifications); + numUsersAdded = modifiedUsers.added.length + modifiedUsers.changed.length; + numPresent = modifiedUsers.present.length; + if (numUsersAdded > 0 || numPresent > 0) { + title = interpolate_text( + ngettext("{numUsersAdded} student has been added to this cohort", + "{numUsersAdded} students have been added to this cohort", numUsersAdded), + {numUsersAdded: numUsersAdded} + ); + + var movedByCohort = {}; + _.each(modifiedUsers.changed, function (changedInfo) { + oldCohort = changedInfo.previous_cohort; + if (oldCohort in movedByCohort) { + movedByCohort[oldCohort] = movedByCohort[oldCohort] + 1; + } + else { + movedByCohort[oldCohort] = 1; + } + }); + + details = []; + for (oldCohort in movedByCohort) { + details.push( + interpolate_text( + ngettext("{numMoved} student was removed from {oldCohort}", + "{numMoved} students were removed from {oldCohort}", movedByCohort[oldCohort]), + {numMoved: movedByCohort[oldCohort], oldCohort: oldCohort} + ) + ); + } + if (numPresent > 0) { + details.push( + interpolate_text( + ngettext("{numPresent} student was already in the cohort", + "{numPresent} students were already in the cohort", numPresent), + {numPresent: numPresent} + ) + ); + } + + this.confirmationNotifications = new NotificationView({ + el: this.$('.cohort-confirmations'), + model: new NotificationModel({ + type: "confirmation", + title: title, + details: details + }) + }); + this.confirmationNotifications.render(); + } + else if (this.confirmationNotifications) { + this.confirmationNotifications.$el.html(''); + this.confirmationNotifications = null; + } + + // Show error messages. + this.undelegateViewEvents(this.errorNotifications); + numErrors = modifiedUsers.unknown.length; + if (numErrors > 0) { + createErrorDetails = function (unknownUsers, showAllErrors) { + var numErrors = unknownUsers.length, details = []; + + for (var i = 0; i < (showAllErrors ? numErrors : Math.min(errorLimit, numErrors)); i++) { + details.push(interpolate_text(gettext("Unknown user: {user}"), {user: unknownUsers[i]})); + } + return details; + }; + + title = interpolate_text( + ngettext("There was an error when trying to add students:", + "There were {numErrors} errors when trying to add students:", numErrors), + {numErrors: numErrors} + ); + details = createErrorDetails(modifiedUsers.unknown, false); + + errorActionCallback = function (view) { + view.model.set("actionText", null); + view.model.set("details", createErrorDetails(modifiedUsers.unknown, true)); + view.render(); + }; + + errorModel = new NotificationModel({ + details: details, + actionText: numErrors > errorLimit ? gettext("View all errors") : null, + actionCallback: errorActionCallback, + actionClass: 'action-expand' + }); + + this.showErrorMessage(title, false, errorModel); + } + else if (this.errorNotifications) { + this.errorNotifications.$el.html(''); + this.errorNotifications = null; + } + } }); - this.errorNotifications.render(); - }, - - addNotifications: function(modifiedUsers) { - var oldCohort, title, details, numPresent, numUsersAdded, numErrors, - createErrorDetails, errorActionCallback, errorModel, - errorLimit = 5; - - // Show confirmation messages. - this.undelegateViewEvents(this.confirmationNotifications); - numUsersAdded = modifiedUsers.added.length + modifiedUsers.changed.length; - numPresent = modifiedUsers.present.length; - if (numUsersAdded > 0 || numPresent > 0) { - title = interpolate_text( - ngettext("{numUsersAdded} student has been added to this cohort", - "{numUsersAdded} students have been added to this cohort", numUsersAdded), - {numUsersAdded: numUsersAdded} - ); - - var movedByCohort = {}; - _.each(modifiedUsers.changed, function (changedInfo) { - oldCohort = changedInfo.previous_cohort; - if (oldCohort in movedByCohort) { - movedByCohort[oldCohort] = movedByCohort[oldCohort] + 1; - } - else { - movedByCohort[oldCohort] = 1; - } - }); - - details = []; - for (oldCohort in movedByCohort) { - details.push( - interpolate_text( - ngettext("{numMoved} student was removed from {oldCohort}", - "{numMoved} students were removed from {oldCohort}", movedByCohort[oldCohort]), - {numMoved: movedByCohort[oldCohort], oldCohort: oldCohort} - ) - ); - } - if (numPresent > 0) { - details.push( - interpolate_text( - ngettext("{numPresent} student was already in the cohort", - "{numPresent} students were already in the cohort", numPresent), - {numPresent: numPresent} - ) - ); - } - - this.confirmationNotifications = new NotificationView({ - el: this.$('.cohort-confirmations'), - model: new NotificationModel({ - type: "confirmation", - title: title, - details: details - }) - }); - this.confirmationNotifications.render(); - } - else if (this.confirmationNotifications) { - this.confirmationNotifications.$el.html(''); - this.confirmationNotifications = null; - } - - // Show error messages. - this.undelegateViewEvents(this.errorNotifications); - numErrors = modifiedUsers.unknown.length; - if (numErrors > 0) { - createErrorDetails = function (unknownUsers, showAllErrors) { - var numErrors = unknownUsers.length, details = []; - - for (var i = 0; i < (showAllErrors ? numErrors : Math.min(errorLimit, numErrors)); i++) { - details.push(interpolate_text(gettext("Unknown user: {user}"), {user: unknownUsers[i]})); - } - return details; - }; - - title = interpolate_text( - ngettext("There was an error when trying to add students:", - "There were {numErrors} errors when trying to add students:", numErrors), - {numErrors: numErrors} - ); - details = createErrorDetails(modifiedUsers.unknown, false); - - errorActionCallback = function (view) { - view.model.set("actionText", null); - view.model.set("details", createErrorDetails(modifiedUsers.unknown, true)); - view.render(); - }; - - errorModel = new NotificationModel({ - details: details, - actionText: numErrors > errorLimit ? gettext("View all errors") : null, - actionCallback: errorActionCallback, - actionClass: 'action-expand' - }); - - this.showErrorMessage(title, false, errorModel); - } - else if (this.errorNotifications) { - this.errorNotifications.$el.html(''); - this.errorNotifications = null; - } - } + return CohortEditorView; }); -}).call(this, Backbone, _, $, gettext, ngettext, interpolate_text, edx.groups.CohortFormView, - NotificationModel, NotificationView); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/views/cohort_form.js b/lms/static/js/groups/views/cohort_form.js index 2eba90da49..3a4f755e15 100644 --- a/lms/static/js/groups/views/cohort_form.js +++ b/lms/static/js/groups/views/cohort_form.js @@ -1,172 +1,173 @@ -var edx = edx || {}; - -(function($, _, Backbone, gettext, interpolate_text, CohortModel, NotificationModel, NotificationView) { +;(function (define) { 'use strict'; + define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/models/cohort', + 'js/models/notification', 'js/views/notification'], + function($, _, Backbone, gettext, CohortModel) { - edx.groups = edx.groups || {}; + var CohortFormView = Backbone.View.extend({ + events : { + 'change .cohort-management-details-association-course input': 'onRadioButtonChange' + }, - edx.groups.CohortFormView = Backbone.View.extend({ - events : { - 'change .cohort-management-details-association-course input': 'onRadioButtonChange' - }, + initialize: function(options) { + this.template = _.template($('#cohort-form-tpl').text()); + this.contentGroups = options.contentGroups; + this.context = options.context; + }, - initialize: function(options) { - this.template = _.template($('#cohort-form-tpl').text()); - this.contentGroups = options.contentGroups; - this.context = options.context; - }, + showNotification: function(options, beforeElement) { + var model = new NotificationModel(options); + this.removeNotification(); + this.notification = new NotificationView({ + model: model + }); + beforeElement.before(this.notification.$el); + this.notification.render(); + }, - showNotification: function(options, beforeElement) { - var model = new NotificationModel(options); - this.removeNotification(); - this.notification = new NotificationView({ - model: model + removeNotification: function() { + if (this.notification) { + this.notification.remove(); + } + }, + + render: function() { + this.$el.html(this.template({ + cohort: this.model, + isDefaultCohort: this.isDefault(this.model.get('name')), + contentGroups: this.contentGroups, + studioGroupConfigurationsUrl: this.context.studioGroupConfigurationsUrl + })); + return this; + }, + + isDefault: function(name) { + var cohorts = this.model.collection; + if (_.isUndefined(cohorts)) { + return false; + } + var randomModels = cohorts.where({assignment_type:'random'}); + return (randomModels.length === 1) && (randomModels[0].get('name') === name); + }, + + onRadioButtonChange: function(event) { + var target = $(event.currentTarget), + groupsEnabled = target.val() === 'yes'; + if (!groupsEnabled) { + // If the user has chosen 'no', then clear the selection by setting + // it to the first option which represents no selection. + this.$('.input-cohort-group-association').val('None'); + } + // Enable the select if the user has chosen groups, else disable it + this.$('.input-cohort-group-association').prop('disabled', !groupsEnabled); + }, + + hasAssociatedContentGroup: function() { + return this.$('.radio-yes').prop('checked'); + }, + + getSelectedContentGroup: function() { + var selectValue = this.$('.input-cohort-group-association').val(), + ids, groupId, userPartitionId, i, contentGroup; + if (!this.hasAssociatedContentGroup() || selectValue === 'None') { + return null; + } + ids = selectValue.split(':'); + groupId = parseInt(ids[0]); + userPartitionId = parseInt(ids[1]); + for (i=0; i < this.contentGroups.length; i++) { + contentGroup = this.contentGroups[i]; + if (contentGroup.get('id') === groupId && contentGroup.get('user_partition_id') === userPartitionId) { + return contentGroup; + } + } + return null; + }, + + getUpdatedCohortName: function() { + var cohortName = this.$('.cohort-name').val(); + return cohortName ? cohortName.trim() : ''; + }, + + getAssignmentType: function() { + return this.$('input[name="cohort-assignment-type"]:checked').val(); + }, + + showMessage: function(message, type, details) { + this.showNotification( + {type: type || 'confirmation', title: message, details: details}, + this.$('.form-fields') + ); + }, + + validate: function(fieldData) { + var errorMessages; + errorMessages = []; + if (!fieldData.name) { + errorMessages.push(gettext('You must specify a name for the cohort')); + } + if (this.hasAssociatedContentGroup() && fieldData.group_id === null) { + if (this.$('.input-cohort-group-association').val() === 'None') { + errorMessages.push(gettext('You did not select a content group')); + } else { + // If a value was selected, then it must be for a non-existent/deleted content group + errorMessages.push(gettext('The selected content group does not exist')); + } + } + return errorMessages; + }, + + saveForm: function() { + var self = this, + cohort = this.model, + saveOperation = $.Deferred(), + isUpdate = !_.isUndefined(this.model.id), + fieldData, selectedContentGroup, selectedAssignmentType, errorMessages, showErrorMessage; + showErrorMessage = function(message, details) { + self.showMessage(message, 'error', details); + }; + this.removeNotification(); + selectedContentGroup = this.getSelectedContentGroup(); + selectedAssignmentType = this.getAssignmentType(); + fieldData = { + name: this.getUpdatedCohortName(), + group_id: selectedContentGroup ? selectedContentGroup.id : null, + user_partition_id: selectedContentGroup ? selectedContentGroup.get('user_partition_id') : null, + assignment_type: selectedAssignmentType + }; + errorMessages = this.validate(fieldData); + + if (errorMessages.length > 0) { + showErrorMessage( + isUpdate ? gettext("The cohort cannot be saved") : gettext("The cohort cannot be added"), + errorMessages + ); + saveOperation.reject(); + } else { + cohort.save( + fieldData, {patch: isUpdate, wait: true} + ).done(function(result) { + cohort.id = result.id; + self.render(); // re-render to remove any now invalid error messages + saveOperation.resolve(); + }).fail(function(result) { + var errorMessage = null; + try { + var jsonResponse = JSON.parse(result.responseText); + errorMessage = jsonResponse.error; + } catch(e) { + // Ignore the exception and show the default error message instead. + } + if (!errorMessage) { + errorMessage = gettext("We've encountered an error. Refresh your browser and then try again."); + } + showErrorMessage(errorMessage); + saveOperation.reject(); + }); + } + return saveOperation.promise(); + } }); - beforeElement.before(this.notification.$el); - this.notification.render(); - }, - - removeNotification: function() { - if (this.notification) { - this.notification.remove(); - } - }, - - render: function() { - this.$el.html(this.template({ - cohort: this.model, - isDefaultCohort: this.isDefault(this.model.get('name')), - contentGroups: this.contentGroups, - studioGroupConfigurationsUrl: this.context.studioGroupConfigurationsUrl - })); - return this; - }, - - isDefault: function(name) { - var cohorts = this.model.collection; - if (_.isUndefined(cohorts)) { - return false; - } - var randomModels = cohorts.where({assignment_type:'random'}); - return (randomModels.length === 1) && (randomModels[0].get('name') === name); - }, - - onRadioButtonChange: function(event) { - var target = $(event.currentTarget), - groupsEnabled = target.val() === 'yes'; - if (!groupsEnabled) { - // If the user has chosen 'no', then clear the selection by setting - // it to the first option which represents no selection. - this.$('.input-cohort-group-association').val('None'); - } - // Enable the select if the user has chosen groups, else disable it - this.$('.input-cohort-group-association').prop('disabled', !groupsEnabled); - }, - - hasAssociatedContentGroup: function() { - return this.$('.radio-yes').prop('checked'); - }, - - getSelectedContentGroup: function() { - var selectValue = this.$('.input-cohort-group-association').val(), - ids, groupId, userPartitionId, i, contentGroup; - if (!this.hasAssociatedContentGroup() || selectValue === 'None') { - return null; - } - ids = selectValue.split(':'); - groupId = parseInt(ids[0]); - userPartitionId = parseInt(ids[1]); - for (i=0; i < this.contentGroups.length; i++) { - contentGroup = this.contentGroups[i]; - if (contentGroup.get('id') === groupId && contentGroup.get('user_partition_id') === userPartitionId) { - return contentGroup; - } - } - return null; - }, - - getUpdatedCohortName: function() { - var cohortName = this.$('.cohort-name').val(); - return cohortName ? cohortName.trim() : ''; - }, - - getAssignmentType: function() { - return this.$('input[name="cohort-assignment-type"]:checked').val(); - }, - - showMessage: function(message, type, details) { - this.showNotification( - {type: type || 'confirmation', title: message, details: details}, - this.$('.form-fields') - ); - }, - - validate: function(fieldData) { - var errorMessages; - errorMessages = []; - if (!fieldData.name) { - errorMessages.push(gettext('You must specify a name for the cohort')); - } - if (this.hasAssociatedContentGroup() && fieldData.group_id === null) { - if (this.$('.input-cohort-group-association').val() === 'None') { - errorMessages.push(gettext('You did not select a content group')); - } else { - // If a value was selected, then it must be for a non-existent/deleted content group - errorMessages.push(gettext('The selected content group does not exist')); - } - } - return errorMessages; - }, - - saveForm: function() { - var self = this, - cohort = this.model, - saveOperation = $.Deferred(), - isUpdate = !_.isUndefined(this.model.id), - fieldData, selectedContentGroup, selectedAssignmentType, errorMessages, showErrorMessage; - showErrorMessage = function(message, details) { - self.showMessage(message, 'error', details); - }; - this.removeNotification(); - selectedContentGroup = this.getSelectedContentGroup(); - selectedAssignmentType = this.getAssignmentType(); - fieldData = { - name: this.getUpdatedCohortName(), - group_id: selectedContentGroup ? selectedContentGroup.id : null, - user_partition_id: selectedContentGroup ? selectedContentGroup.get('user_partition_id') : null, - assignment_type: selectedAssignmentType - }; - errorMessages = this.validate(fieldData); - - if (errorMessages.length > 0) { - showErrorMessage( - isUpdate ? gettext("The cohort cannot be saved") : gettext("The cohort cannot be added"), - errorMessages - ); - saveOperation.reject(); - } else { - cohort.save( - fieldData, {patch: isUpdate, wait: true} - ).done(function(result) { - cohort.id = result.id; - self.render(); // re-render to remove any now invalid error messages - saveOperation.resolve(); - }).fail(function(result) { - var errorMessage = null; - try { - var jsonResponse = JSON.parse(result.responseText); - errorMessage = jsonResponse.error; - } catch(e) { - // Ignore the exception and show the default error message instead. - } - if (!errorMessage) { - errorMessage = gettext("We've encountered an error. Refresh your browser and then try again."); - } - showErrorMessage(errorMessage); - saveOperation.reject(); - }); - } - return saveOperation.promise(); - } - }); -}).call(this, $, _, Backbone, gettext, interpolate_text, edx.groups.CohortModel, NotificationModel, NotificationView); + return CohortFormView; + }); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/views/cohorts.js b/lms/static/js/groups/views/cohorts.js index 0d5714d901..da06366fc7 100644 --- a/lms/static/js/groups/views/cohorts.js +++ b/lms/static/js/groups/views/cohorts.js @@ -1,310 +1,312 @@ -var edx = edx || {}; - -(function($, _, Backbone, gettext, interpolate_text, CohortModel, CohortEditorView, CohortFormView, - CourseCohortSettingsNotificationView, NotificationModel, NotificationView, FileUploaderView, - InlineDiscussionsView, CourseWideDiscussionsView) { +;(function (define) { 'use strict'; + define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/models/cohort', + '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', + 'js/views/file_uploader', 'js/models/notification', 'js/views/notification', 'string_utils'], + function($, _, Backbone, gettext, CohortModel, CohortEditorView, CohortFormView, + CourseCohortSettingsNotificationView, InlineDiscussionsView, CourseWideDiscussionsView) { - var hiddenClass = 'is-hidden', - disabledClass = 'is-disabled'; + var hiddenClass = 'is-hidden', + disabledClass = 'is-disabled'; - edx.groups = edx.groups || {}; - edx.groups.CohortsView = Backbone.View.extend({ - events : { - 'change .cohort-select': 'onCohortSelected', - 'change .cohorts-state': 'onCohortsEnabledChanged', - 'click .action-create': 'showAddCohortForm', - 'click .cohort-management-add-form .action-save': 'saveAddCohortForm', - 'click .cohort-management-add-form .action-cancel': 'cancelAddCohortForm', - 'click .link-cross-reference': 'showSection', - 'click .toggle-cohort-management-secondary': 'showCsvUpload', - 'click .toggle-cohort-management-discussions': 'showDiscussionTopics' - }, + var CohortsView = Backbone.View.extend({ + events : { + 'change .cohort-select': 'onCohortSelected', + 'change .cohorts-state': 'onCohortsEnabledChanged', + 'click .action-create': 'showAddCohortForm', + 'click .cohort-management-add-form .action-save': 'saveAddCohortForm', + 'click .cohort-management-add-form .action-cancel': 'cancelAddCohortForm', + 'click .link-cross-reference': 'showSection', + 'click .toggle-cohort-management-secondary': 'showCsvUpload', + 'click .toggle-cohort-management-discussions': 'showDiscussionTopics' + }, - initialize: function(options) { - var model = this.model; + initialize: function(options) { + var model = this.model; - this.template = _.template($('#cohorts-tpl').text()); - this.selectorTemplate = _.template($('#cohort-selector-tpl').text()); - this.context = options.context; - this.contentGroups = options.contentGroups; - this.cohortSettings = options.cohortSettings; - model.on('sync', this.onSync, this); + this.template = _.template($('#cohorts-tpl').text()); + this.selectorTemplate = _.template($('#cohort-selector-tpl').text()); + this.context = options.context; + this.contentGroups = options.contentGroups; + this.cohortSettings = options.cohortSettings; + model.on('sync', this.onSync, this); - // Update cohort counts when the user clicks back on the cohort management tab - // (for example, after uploading a csv file of cohort assignments and then - // checking results on data download tab). - $(this.getSectionCss('cohort_management')).click(function () { - model.fetch(); - }); - }, - - render: function() { - this.$el.html(this.template({ - cohorts: this.model.models, - cohortsEnabled: this.cohortSettings.get('is_cohorted') - })); - this.onSync(); - return this; - }, - - renderSelector: function(selectedCohort) { - this.$('.cohort-select').html(this.selectorTemplate({ - cohorts: this.model.models, - selectedCohort: selectedCohort - })); - }, - - renderCourseCohortSettingsNotificationView: function() { - var cohortStateMessageNotificationView = new CourseCohortSettingsNotificationView({ - el: $('.cohort-state-message'), - cohortEnabled: this.getCohortsEnabled() - }); - cohortStateMessageNotificationView.render(); - }, - - onSync: function(model, response, options) { - var selectedCohort = this.lastSelectedCohortId && this.model.get(this.lastSelectedCohortId), - hasCohorts = this.model.length > 0, - cohortNavElement = this.$('.cohort-management-nav'), - additionalCohortControlElement = this.$('.wrapper-cohort-supplemental'), - isModelUpdate; - isModelUpdate = function() { - // Distinguish whether this is a sync event for just one model, or if it is for - // an entire collection. - return options && options.patch && response.hasOwnProperty('user_partition_id'); - }; - this.hideAddCohortForm(); - if (isModelUpdate()) { - // Refresh the selector in case the model's name changed - this.renderSelector(selectedCohort); - } else if (hasCohorts) { - cohortNavElement.removeClass(hiddenClass); - additionalCohortControlElement.removeClass(hiddenClass); - this.renderSelector(selectedCohort); - if (selectedCohort) { - this.showCohortEditor(selectedCohort); - } - } else { - cohortNavElement.addClass(hiddenClass); - additionalCohortControlElement.addClass(hiddenClass); - this.showNotification({ - type: 'warning', - title: gettext('You currently have no cohorts configured'), - actionText: gettext('Add Cohort'), - actionClass: 'action-create', - actionIconClass: 'fa-plus' - }); - } - }, - - getSelectedCohort: function() { - var id = this.$('.cohort-select').val(); - return id && this.model.get(parseInt(id)); - }, - - onCohortSelected: function(event) { - event.preventDefault(); - var selectedCohort = this.getSelectedCohort(); - this.lastSelectedCohortId = selectedCohort.get('id'); - this.showCohortEditor(selectedCohort); - }, - - onCohortsEnabledChanged: function(event) { - event.preventDefault(); - this.saveCohortSettings(); - }, - - saveCohortSettings: function() { - var self = this, - cohortSettings, - fieldData = {is_cohorted: this.getCohortsEnabled()}; - cohortSettings = this.cohortSettings; - cohortSettings.save( - fieldData, {patch: true, wait: true} - ).done(function() { - self.render(); - self.renderCourseCohortSettingsNotificationView(); - }).fail(function(result) { - self.showNotification({ - type: 'error', - title: gettext("We've encountered an error. Refresh your browser and then try again.")}, - self.$('.cohorts-state-section') - ); - }); - }, - - getCohortsEnabled: function() { - return this.$('.cohorts-state').prop('checked'); - }, - - showCohortEditor: function(cohort) { - this.removeNotification(); - if (this.editor) { - this.editor.setCohort(cohort); - $('.cohort-management-group .group-header-title').focus(); - } else { - this.editor = new CohortEditorView({ - el: this.$('.cohort-management-group'), - model: cohort, - cohorts: this.model, - contentGroups: this.contentGroups, - context: this.context - }); - this.editor.render(); - $('.cohort-management-group .group-header-title').focus(); - } - }, - - showNotification: function(options, beforeElement) { - var model = new NotificationModel(options); - this.removeNotification(); - this.notification = new NotificationView({ - model: model - }); - - if (!beforeElement) { - beforeElement = this.$('.cohort-management-group'); - } - beforeElement.before(this.notification.$el); - - this.notification.render(); - }, - - removeNotification: function() { - if (this.notification) { - this.notification.remove(); - } - if (this.cohortFormView) { - this.cohortFormView.removeNotification(); - } - }, - - showAddCohortForm: function(event) { - var newCohort; - event.preventDefault(); - this.removeNotification(); - newCohort = new CohortModel(); - newCohort.url = this.model.url; - this.cohortFormView = new CohortFormView({ - model: newCohort, - contentGroups: this.contentGroups, - context: this.context - }); - this.cohortFormView.render(); - this.$('.cohort-management-add-form').append(this.cohortFormView.$el); - this.cohortFormView.$('.cohort-name').focus(); - this.setCohortEditorVisibility(false); - }, - - hideAddCohortForm: function() { - this.setCohortEditorVisibility(true); - if (this.cohortFormView) { - this.cohortFormView.remove(); - this.cohortFormView = null; - } - }, - - setCohortEditorVisibility: function(showEditor) { - if (showEditor) { - this.$('.cohorts-state-section').removeClass(disabledClass).attr('aria-disabled', false); - this.$('.cohort-management-group').removeClass(hiddenClass); - this.$('.cohort-management-nav').removeClass(disabledClass).attr('aria-disabled', false); - } else { - this.$('.cohorts-state-section').addClass(disabledClass).attr('aria-disabled', true); - this.$('.cohort-management-group').addClass(hiddenClass); - this.$('.cohort-management-nav').addClass(disabledClass).attr('aria-disabled', true); - } - }, - - saveAddCohortForm: function(event) { - var self = this, - newCohort = this.cohortFormView.model; - event.preventDefault(); - this.removeNotification(); - this.cohortFormView.saveForm() - .done(function() { - self.lastSelectedCohortId = newCohort.id; - self.model.fetch().done(function() { - self.showNotification({ - type: 'confirmation', - title: interpolate_text( - gettext('The {cohortGroupName} cohort has been created. You can manually add students to this cohort below.'), - {cohortGroupName: newCohort.get('name')} - ) - }); + // Update cohort counts when the user clicks back on the cohort management tab + // (for example, after uploading a csv file of cohort assignments and then + // checking results on data download tab). + $(this.getSectionCss('cohort_management')).click(function () { + model.fetch(); }); - }); - }, + }, - cancelAddCohortForm: function(event) { - event.preventDefault(); - this.removeNotification(); - this.onSync(); - }, + render: function() { + this.$el.html(this.template({ + cohorts: this.model.models, + cohortsEnabled: this.cohortSettings.get('is_cohorted') + })); + this.onSync(); + return this; + }, - showSection: function(event) { - event.preventDefault(); - var section = $(event.currentTarget).data("section"); - $(this.getSectionCss(section)).click(); - $(window).scrollTop(0); - }, + renderSelector: function(selectedCohort) { + this.$('.cohort-select').html(this.selectorTemplate({ + cohorts: this.model.models, + selectedCohort: selectedCohort + })); + }, - showCsvUpload: function(event) { - event.preventDefault(); + renderCourseCohortSettingsNotificationView: function() { + var cohortStateMessageNotificationView = new CourseCohortSettingsNotificationView({ + el: $('.cohort-state-message'), + cohortEnabled: this.getCohortsEnabled() + }); + cohortStateMessageNotificationView.render(); + }, - $(event.currentTarget).addClass(hiddenClass); - var uploadElement = this.$('.csv-upload').removeClass(hiddenClass); - - if (!this.fileUploaderView) { - this.fileUploaderView = new FileUploaderView({ - el: uploadElement, - title: gettext("Assign students to cohorts by uploading a CSV file."), - inputLabel: gettext("Choose a .csv file"), - inputTip: gettext("Only properly formatted .csv files will be accepted."), - submitButtonText: gettext("Upload File and Assign Students"), - extensions: ".csv", - url: this.context.uploadCohortsCsvUrl, - successNotification: function (file, event, data) { - var message = interpolate_text(gettext( - "Your file '{file}' has been uploaded. Allow a few minutes for processing." - ), {file: file}); - return new NotificationModel({ - type: "confirmation", - title: message + onSync: function(model, response, options) { + var selectedCohort = this.lastSelectedCohortId && this.model.get(this.lastSelectedCohortId), + hasCohorts = this.model.length > 0, + cohortNavElement = this.$('.cohort-management-nav'), + additionalCohortControlElement = this.$('.wrapper-cohort-supplemental'), + isModelUpdate; + isModelUpdate = function() { + // Distinguish whether this is a sync event for just one model, or if it is for + // an entire collection. + return options && options.patch && response.hasOwnProperty('user_partition_id'); + }; + this.hideAddCohortForm(); + if (isModelUpdate()) { + // Refresh the selector in case the model's name changed + this.renderSelector(selectedCohort); + } else if (hasCohorts) { + cohortNavElement.removeClass(hiddenClass); + additionalCohortControlElement.removeClass(hiddenClass); + this.renderSelector(selectedCohort); + if (selectedCohort) { + this.showCohortEditor(selectedCohort); + } + } else { + cohortNavElement.addClass(hiddenClass); + additionalCohortControlElement.addClass(hiddenClass); + this.showNotification({ + type: 'warning', + title: gettext('You currently have no cohorts configured'), + actionText: gettext('Add Cohort'), + actionClass: 'action-create', + actionIconClass: 'fa-plus' }); } - }).render(); - this.$('#file-upload-form-file').focus(); - } - }, - showDiscussionTopics: function(event) { - event.preventDefault(); + }, - $(event.currentTarget).addClass(hiddenClass); - var cohortDiscussionsElement = this.$('.cohort-discussions-nav').removeClass(hiddenClass); + getSelectedCohort: function() { + var id = this.$('.cohort-select').val(); + return id && this.model.get(parseInt(id)); + }, - if (!this.CourseWideDiscussionsView) { - this.CourseWideDiscussionsView = new CourseWideDiscussionsView({ - el: cohortDiscussionsElement, - model: this.context.discussionTopicsSettingsModel, - cohortSettings: this.cohortSettings - }).render(); - } - if(!this.InlineDiscussionsView) { - this.InlineDiscussionsView = new InlineDiscussionsView({ - el: cohortDiscussionsElement, - model: this.context.discussionTopicsSettingsModel, - cohortSettings: this.cohortSettings - }).render(); - } - }, + onCohortSelected: function(event) { + event.preventDefault(); + var selectedCohort = this.getSelectedCohort(); + this.lastSelectedCohortId = selectedCohort.get('id'); + this.showCohortEditor(selectedCohort); + }, - getSectionCss: function (section) { - return ".instructor-nav .nav-item a[data-section='" + section + "']"; - } + onCohortsEnabledChanged: function(event) { + event.preventDefault(); + this.saveCohortSettings(); + }, + + saveCohortSettings: function() { + var self = this, + cohortSettings, + fieldData = {is_cohorted: this.getCohortsEnabled()}; + cohortSettings = this.cohortSettings; + cohortSettings.save( + fieldData, {patch: true, wait: true} + ).done(function() { + self.render(); + self.renderCourseCohortSettingsNotificationView(); + }).fail(function(result) { + self.showNotification({ + type: 'error', + title: gettext("We've encountered an error. Refresh your browser and then try again.")}, + self.$('.cohorts-state-section') + ); + }); + }, + + getCohortsEnabled: function() { + return this.$('.cohorts-state').prop('checked'); + }, + + showCohortEditor: function(cohort) { + this.removeNotification(); + if (this.editor) { + this.editor.setCohort(cohort); + $('.cohort-management-group .group-header-title').focus(); + } else { + this.editor = new CohortEditorView({ + el: this.$('.cohort-management-group'), + model: cohort, + cohorts: this.model, + contentGroups: this.contentGroups, + context: this.context + }); + this.editor.render(); + $('.cohort-management-group .group-header-title').focus(); + } + }, + + showNotification: function(options, beforeElement) { + var model = new NotificationModel(options); + this.removeNotification(); + this.notification = new NotificationView({ + model: model + }); + + if (!beforeElement) { + beforeElement = this.$('.cohort-management-group'); + } + beforeElement.before(this.notification.$el); + + this.notification.render(); + }, + + removeNotification: function() { + if (this.notification) { + this.notification.remove(); + } + if (this.cohortFormView) { + this.cohortFormView.removeNotification(); + } + }, + + showAddCohortForm: function(event) { + var newCohort; + event.preventDefault(); + this.removeNotification(); + newCohort = new CohortModel(); + newCohort.url = this.model.url; + this.cohortFormView = new CohortFormView({ + model: newCohort, + contentGroups: this.contentGroups, + context: this.context + }); + this.cohortFormView.render(); + this.$('.cohort-management-add-form').append(this.cohortFormView.$el); + this.cohortFormView.$('.cohort-name').focus(); + this.setCohortEditorVisibility(false); + }, + + hideAddCohortForm: function() { + this.setCohortEditorVisibility(true); + if (this.cohortFormView) { + this.cohortFormView.remove(); + this.cohortFormView = null; + } + }, + + setCohortEditorVisibility: function(showEditor) { + if (showEditor) { + this.$('.cohorts-state-section').removeClass(disabledClass).attr('aria-disabled', false); + this.$('.cohort-management-group').removeClass(hiddenClass); + this.$('.cohort-management-nav').removeClass(disabledClass).attr('aria-disabled', false); + } else { + this.$('.cohorts-state-section').addClass(disabledClass).attr('aria-disabled', true); + this.$('.cohort-management-group').addClass(hiddenClass); + this.$('.cohort-management-nav').addClass(disabledClass).attr('aria-disabled', true); + } + }, + + saveAddCohortForm: function(event) { + var self = this, + newCohort = this.cohortFormView.model; + event.preventDefault(); + this.removeNotification(); + this.cohortFormView.saveForm() + .done(function() { + self.lastSelectedCohortId = newCohort.id; + self.model.fetch().done(function() { + self.showNotification({ + type: 'confirmation', + title: interpolate_text( + gettext('The {cohortGroupName} cohort has been created. You can manually add students to this cohort below.'), + {cohortGroupName: newCohort.get('name')} + ) + }); + }); + }); + }, + + cancelAddCohortForm: function(event) { + event.preventDefault(); + this.removeNotification(); + this.onSync(); + }, + + showSection: function(event) { + event.preventDefault(); + var section = $(event.currentTarget).data("section"); + $(this.getSectionCss(section)).click(); + $(window).scrollTop(0); + }, + + showCsvUpload: function(event) { + event.preventDefault(); + + $(event.currentTarget).addClass(hiddenClass); + var uploadElement = this.$('.csv-upload').removeClass(hiddenClass); + + if (!this.fileUploaderView) { + this.fileUploaderView = new FileUploaderView({ + el: uploadElement, + title: gettext("Assign students to cohorts by uploading a CSV file."), + inputLabel: gettext("Choose a .csv file"), + inputTip: gettext("Only properly formatted .csv files will be accepted."), + submitButtonText: gettext("Upload File and Assign Students"), + extensions: ".csv", + url: this.context.uploadCohortsCsvUrl, + successNotification: function (file, event, data) { + var message = interpolate_text(gettext( + "Your file '{file}' has been uploaded. Allow a few minutes for processing." + ), {file: file}); + return new NotificationModel({ + type: "confirmation", + title: message + }); + } + }).render(); + this.$('#file-upload-form-file').focus(); + } + }, + showDiscussionTopics: function(event) { + event.preventDefault(); + + $(event.currentTarget).addClass(hiddenClass); + var cohortDiscussionsElement = this.$('.cohort-discussions-nav').removeClass(hiddenClass); + + if (!this.CourseWideDiscussionsView) { + this.CourseWideDiscussionsView = new CourseWideDiscussionsView({ + el: cohortDiscussionsElement, + model: this.context.discussionTopicsSettingsModel, + cohortSettings: this.cohortSettings + }).render(); + } + if(!this.InlineDiscussionsView) { + this.InlineDiscussionsView = new InlineDiscussionsView({ + el: cohortDiscussionsElement, + model: this.context.discussionTopicsSettingsModel, + cohortSettings: this.cohortSettings + }).render(); + } + }, + + getSectionCss: function (section) { + return ".instructor-nav .nav-item a[data-section='" + section + "']"; + } + }); + return CohortsView; }); -}).call(this, $, _, Backbone, gettext, interpolate_text, edx.groups.CohortModel, edx.groups.CohortEditorView, - edx.groups.CohortFormView, edx.groups.CourseCohortSettingsNotificationView, NotificationModel, NotificationView, - FileUploaderView, edx.groups.InlineDiscussionsView, edx.groups.CourseWideDiscussionsView); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/views/cohorts_dashboard_factory.js b/lms/static/js/groups/views/cohorts_dashboard_factory.js index 3ddf229220..f6f3bb7e1d 100644 --- a/lms/static/js/groups/views/cohorts_dashboard_factory.js +++ b/lms/static/js/groups/views/cohorts_dashboard_factory.js @@ -1,14 +1,21 @@ ;(function (define, undefined) { 'use strict'; define(['jquery', 'js/groups/views/cohorts', 'js/groups/collections/cohort', 'js/groups/models/course_cohort_settings', - 'js/groups/models/cohort_discussions'], - function($) { + 'js/groups/models/cohort_discussions', 'js/groups/models/content_group'], + function($, CohortsView, CohortCollection, CourseCohortSettingsModel, DiscussionTopicsSettingsModel, ContentGroupModel) { return function(contentGroups, studioGroupConfigurationsUrl) { + var contentGroupModels = $.map(contentGroups, function(group) { + return new ContentGroupModel({ + id: group.id, + name: group.name, + user_partition_id: group.user_partition_id + }); + }); - var cohorts = new edx.groups.CohortCollection(), - courseCohortSettings = new edx.groups.CourseCohortSettingsModel(), - discussionTopicsSettings = new edx.groups.DiscussionTopicsSettingsModel(); + var cohorts = new CohortCollection(), + courseCohortSettings = new CourseCohortSettingsModel(), + discussionTopicsSettings = new DiscussionTopicsSettingsModel(); var cohortManagementElement = $('.cohort-management'); @@ -16,10 +23,10 @@ courseCohortSettings.url = cohortManagementElement.data('course_cohort_settings_url'); discussionTopicsSettings.url = cohortManagementElement.data('discussion-topics-url'); - var cohortsView = new edx.groups.CohortsView({ + var cohortsView = new CohortsView({ el: cohortManagementElement, model: cohorts, - contentGroups: contentGroups, + contentGroups: contentGroupModels, cohortSettings: courseCohortSettings, context: { discussionTopicsSettingsModel: discussionTopicsSettings, diff --git a/lms/static/js/groups/views/course_cohort_settings_notification.js b/lms/static/js/groups/views/course_cohort_settings_notification.js index e675e3440c..78ba1e30e7 100644 --- a/lms/static/js/groups/views/course_cohort_settings_notification.js +++ b/lms/static/js/groups/views/course_cohort_settings_notification.js @@ -1,31 +1,30 @@ -var edx = edx || {}; - -(function($, _, Backbone, gettext) { +;(function (define) { 'use strict'; + define(['jquery', 'underscore', 'backbone', 'gettext'], function($, _, Backbone, gettext) { - edx.groups = edx.groups || {}; + var CourseCohortSettingsNotificationView = Backbone.View.extend({ + initialize: function(options) { + this.template = _.template($('#cohort-state-tpl').text()); + this.cohortEnabled = options.cohortEnabled; + }, - edx.groups.CourseCohortSettingsNotificationView = Backbone.View.extend({ - initialize: function(options) { - this.template = _.template($('#cohort-state-tpl').text()); - this.cohortEnabled = options.cohortEnabled; - }, + render: function() { + this.$el.html(this.template({})); + this.showCohortStateMessage(); + return this; + }, - render: function() { - this.$el.html(this.template({})); - this.showCohortStateMessage(); - return this; - }, + showCohortStateMessage: function () { + var actionToggleMessage = this.$('.action-toggle-message'); - showCohortStateMessage: function () { - var actionToggleMessage = this.$('.action-toggle-message'); - - AnimationUtil.triggerAnimation(actionToggleMessage); - if (this.cohortEnabled) { - actionToggleMessage.text(gettext('Cohorts Enabled')); - } else { - actionToggleMessage.text(gettext('Cohorts Disabled')); + AnimationUtil.triggerAnimation(actionToggleMessage); + if (this.cohortEnabled) { + actionToggleMessage.text(gettext('Cohorts Enabled')); + } else { + actionToggleMessage.text(gettext('Cohorts Disabled')); + } } - } + }); + return CourseCohortSettingsNotificationView; }); -}).call(this, $, _, Backbone, gettext); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/spec/main.js b/lms/static/js/spec/main.js index ec511a15ed..4ce54d5c53 100644 --- a/lms/static/js/spec/main.js +++ b/lms/static/js/spec/main.js @@ -67,18 +67,6 @@ 'js/models/notification': 'js/models/notification', 'js/views/file_uploader': 'js/views/file_uploader', 'js/views/notification': 'js/views/notification', - 'js/groups/models/cohort': 'js/groups/models/cohort', - 'js/groups/models/content_group': 'js/groups/models/content_group', - 'js/groups/models/course_cohort_settings': 'js/groups/models/course_cohort_settings', - 'js/groups/models/cohort_discussions': 'js/groups/models/cohort_discussions', - 'js/groups/views/cohort_discussions': 'js/groups/views/cohort_discussions', - 'js/groups/views/cohort_discussions_course_wide': 'js/groups/views/cohort_discussions_course_wide', - 'js/groups/views/cohort_discussions_inline': 'js/groups/views/cohort_discussions_inline', - 'js/groups/views/course_cohort_settings_notification': 'js/groups/views/course_cohort_settings_notification', - 'js/groups/collections/cohort': 'js/groups/collections/cohort', - 'js/groups/views/cohort_editor': 'js/groups/views/cohort_editor', - 'js/groups/views/cohort_form': 'js/groups/views/cohort_form', - 'js/groups/views/cohorts': 'js/groups/views/cohorts', 'js/student_account/account': 'js/student_account/account', 'js/student_account/views/FormView': 'js/student_account/views/FormView', 'js/student_account/models/LoginModel': 'js/student_account/models/LoginModel', @@ -301,63 +289,6 @@ exports: 'edx.instructor_dashboard.ecommerce.ExpiryCouponView', deps: ['backbone', 'jquery', 'underscore'] }, - 'js/groups/models/cohort': { - exports: 'edx.groups.CohortModel', - deps: ['backbone'] - }, - 'js/groups/models/content_group': { - exports: 'edx.groups.ContentGroupModel', - deps: ['backbone'] - }, - 'js/groups/models/course_cohort_settings': { - exports: 'edx.groups.CourseCohortSettingsModel', - deps: ['backbone'] - }, - 'js/groups/models/cohort_discussions': { - exports: 'edx.groups.DiscussionTopicsSettingsModel', - deps: ['backbone'] - }, - 'js/groups/views/cohort_discussions': { - exports: 'edx.groups.CohortDiscussionConfigurationView', - deps: ['backbone'] - }, - 'js/groups/views/cohort_discussions_course_wide': { - exports: 'edx.groups.CourseWideDiscussionsView', - deps: ['backbone', 'js/groups/views/cohort_discussions'] - }, - 'js/groups/views/cohort_discussions_inline': { - exports: 'edx.groups.InlineDiscussionsView', - deps: ['backbone', 'js/groups/views/cohort_discussions', 'js/vendor/jquery.qubit'] - }, - 'js/groups/views/course_cohort_settings_notification': { - exports: 'edx.groups.CourseCohortSettingsNotificationView', - deps: ['backbone'] - }, - 'js/groups/collections/cohort': { - exports: 'edx.groups.CohortCollection', - deps: ['backbone', 'js/groups/models/cohort'] - }, - 'js/groups/views/cohort_form': { - exports: 'edx.groups.CohortFormView', - deps: [ - 'backbone', 'jquery', 'underscore', 'js/views/notification', 'js/models/notification', - 'string_utils' - ] - }, - 'js/groups/views/cohort_editor': { - exports: 'edx.groups.CohortEditorView', - deps: [ - 'backbone', 'jquery', 'underscore', 'js/views/notification', 'js/models/notification', - 'string_utils', 'js/groups/views/cohort_form' - ] - }, - 'js/groups/views/cohorts': { - exports: 'edx.groups.CohortsView', - deps: [ - 'jquery', 'underscore', 'backbone', 'gettext', 'string_utils', 'js/groups/views/cohort_editor', - 'js/views/notification', 'js/models/notification', 'js/views/file_uploader' - ] - }, 'js/models/notification': { exports: 'NotificationModel', deps: ['backbone'] diff --git a/lms/static/lms/js/build.js b/lms/static/lms/js/build.js index 6f6b088c6f..75b7be52be 100644 --- a/lms/static/lms/js/build.js +++ b/lms/static/lms/js/build.js @@ -18,6 +18,7 @@ * done. */ modules: getModulesList([ + 'js/groups/views/cohorts_dashboard_factory', 'js/student_account/views/account_settings_factory', 'js/student_account/views/finish_auth_factory', 'js/student_profile/views/learner_profile_factory', diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort_management.html b/lms/templates/instructor/instructor_dashboard_2/cohort_management.html index 70705960e8..db7d3e7dc5 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort_management.html +++ b/lms/templates/instructor/instructor_dashboard_2/cohort_management.html @@ -1,4 +1,5 @@ <%page args="section_data"/> +<%namespace name='static' file='../../static_content.html'/> <%! from django.utils.translation import ugettext as _ from courseware.courses import get_studio_url @@ -16,32 +17,23 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_ -<%block name="headextra"> +<%block name="js_extra"> +<%static:require_module module_name="js/groups/views/cohorts_dashboard_factory" class_name="CohortsFactory"> <% cohorted_user_partition = get_cohorted_user_partition(course.id) content_groups = cohorted_user_partition.groups if cohorted_user_partition else [] %> - - + var cohortUserPartitionId = ${cohorted_user_partition.id if cohorted_user_partition else 'null'}, + contentGroups = [ + % for content_group in content_groups: + { + id: ${content_group.id}, + name: "${content_group.name | h}", + user_partition_id: cohortUserPartitionId + }, + % endfor + ]; + CohortsFactory(contentGroups, '${get_studio_url(course, 'group_configurations') | h}'); +
diff --git a/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html b/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html index be681e0906..97a20bca84 100644 --- a/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html +++ b/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html @@ -56,22 +56,9 @@ from django.core.urlresolvers import reverse <%static:js group='application'/> ## Backbone classes declared explicitly until RequireJS is supported - - - - - - - - - - - - -