Cohort discussion topics via UI in instructor dashboard.

TNL-1256
This commit is contained in:
muzaffaryousaf
2015-02-17 16:51:27 +05:00
committed by Usman Khalid
parent e07f45b5dd
commit e6c75529c0
31 changed files with 2118 additions and 145 deletions

View File

@@ -0,0 +1,14 @@
var edx = edx || {};
(function(Backbone) {
'use strict';
edx.groups = edx.groups || {};
edx.groups.DiscussionTopicsSettingsModel = Backbone.Model.extend({
defaults: {
course_wide_discussions: {},
inline_discussions: {}
}
});
}).call(this, Backbone);

View File

@@ -9,7 +9,8 @@ var edx = edx || {};
idAttribute: 'id',
defaults: {
is_cohorted: false,
cohorted_discussions: [],
cohorted_inline_discussions: [],
cohorted_course_wide_discussions:[],
always_cohort_inline_discussions: true
}
});

View File

@@ -0,0 +1,99 @@
var edx = edx || {};
(function ($, _, Backbone, gettext, interpolate_text, NotificationModel, NotificationView) {
'use strict';
edx.groups = edx.groups || {};
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);
},
/**
* 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;
},
/**
* 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();
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();
},
/**
* 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
);

View File

@@ -0,0 +1,83 @@
var edx = edx || {};
(function ($, _, Backbone, gettext, interpolate_text, CohortDiscussionConfigurationView) {
'use strict';
edx.groups = edx.groups || {};
edx.groups.CourseWideDiscussionsView = CohortDiscussionConfigurationView.extend({
events: {
'change .check-discussion-subcategory-course-wide': 'discussionCategoryStateChanged',
'click .cohort-course-wide-discussions-form .action-save': 'saveCourseWideDiscussionsForm'
},
initialize: function (options) {
this.template = _.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(
this.model.get('course_wide_discussions')
)
}));
this.setDisabled(this.$('.cohort-course-wide-discussions-form .action-save'), true);
},
/**
* 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;
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);

View File

@@ -0,0 +1,145 @@
var edx = edx || {};
(function ($, _, Backbone, gettext, interpolate_text, CohortDiscussionConfigurationView) {
'use strict';
edx.groups = edx.groups || {};
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'
},
initialize: function (options) {
this.template = _.template($('#cohort-discussions-inline-tpl').text());
this.cohortSettings = options.cohortSettings;
},
render: function () {
var alwaysCohortInlineDiscussions = this.cohortSettings.get('always_cohort_inline_discussions');
this.$('.cohort-inline-discussions-nav').html(this.template({
inlineDiscussionTopics: this.getInlineDiscussionsHtml(this.model.get('inline_discussions')),
alwaysCohortInlineDiscussions:alwaysCohortInlineDiscussions
}));
// 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.setElementsEnabled(alwaysCohortInlineDiscussions, true);
},
/**
* 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;
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('');
},
/**
* 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);
},
/**
* 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.
*
* 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 save button for inline discussions.
*/
setSaveButton: function(event) {
this.setDisabled(this.$('.cohort-inline-discussions-form .action-save'), false);
},
/**
* 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')
});
});
}
});
}).call(this, $, _, Backbone, gettext, interpolate_text, edx.groups.CohortDiscussionConfigurationView);

View File

@@ -44,8 +44,7 @@ var edx = edx || {};
renderGroupHeader: function() {
this.$('.cohort-management-group-header').html(this.groupHeaderTemplate({
cohort: this.model,
studioAdvancedSettingsUrl: this.context.studioAdvancedSettingsUrl
cohort: this.model
}));
},

View File

@@ -1,7 +1,8 @@
var edx = edx || {};
(function($, _, Backbone, gettext, interpolate_text, CohortModel, CohortEditorView, CohortFormView,
CourseCohortSettingsNotificationView, NotificationModel, NotificationView, FileUploaderView) {
CourseCohortSettingsNotificationView, NotificationModel, NotificationView, FileUploaderView,
InlineDiscussionsView, CourseWideDiscussionsView) {
'use strict';
var hiddenClass = 'is-hidden',
@@ -17,7 +18,8 @@ var edx = edx || {};
'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-secondary': 'showCsvUpload',
'click .toggle-cohort-management-discussions': 'showDiscussionTopics'
},
initialize: function(options) {
@@ -120,7 +122,7 @@ var edx = edx || {};
fieldData = {is_cohorted: this.getCohortsEnabled()};
cohortSettings = this.cohortSettings;
cohortSettings.save(
fieldData, {wait: true}
fieldData, {patch: true, wait: true}
).done(function() {
self.render();
self.renderCourseCohortSettingsNotificationView();
@@ -277,6 +279,27 @@ var edx = edx || {};
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 + "']";
@@ -284,4 +307,4 @@ var edx = edx || {};
});
}).call(this, $, _, Backbone, gettext, interpolate_text, edx.groups.CohortModel, edx.groups.CohortEditorView,
edx.groups.CohortFormView, edx.groups.CourseCohortSettingsNotificationView, NotificationModel, NotificationView,
FileUploaderView);
FileUploaderView, edx.groups.InlineDiscussionsView, edx.groups.CourseWideDiscussionsView);

View File

@@ -0,0 +1,41 @@
;(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($) {
return function(contentGroups, studioGroupConfigurationsUrl) {
var cohorts = new edx.groups.CohortCollection(),
courseCohortSettings = new edx.groups.CourseCohortSettingsModel(),
discussionTopicsSettings = new edx.groups.DiscussionTopicsSettingsModel();
var cohortManagementElement = $('.cohort-management');
cohorts.url = cohortManagementElement.data('cohorts_url');
courseCohortSettings.url = cohortManagementElement.data('course_cohort_settings_url');
discussionTopicsSettings.url = cohortManagementElement.data('discussion-topics-url');
var cohortsView = new edx.groups.CohortsView({
el: cohortManagementElement,
model: cohorts,
contentGroups: contentGroups,
cohortSettings: courseCohortSettings,
context: {
discussionTopicsSettingsModel: discussionTopicsSettings,
uploadCohortsCsvUrl: cohortManagementElement.data('upload_cohorts_csv_url'),
studioGroupConfigurationsUrl: studioGroupConfigurationsUrl
}
});
cohorts.fetch().done(function() {
courseCohortSettings.fetch().done(function() {
discussionTopicsSettings.fetch().done(function() {
cohortsView.render();
});
});
});
};
});
}).call(this, define || RequireJS.define);