Commit eff80bae by Diana Huang Committed by cahrens

Convert cohort JS to use RequireJS.

parent 1ceb8a0d
var edx = edx || {};
(function(Backbone, CohortModel) {
;(function (define) {
'use strict';
define(['backbone', 'js/groups/models/cohort'], function(Backbone, CohortModel) {
edx.groups = edx.groups || {};
edx.groups.CohortCollection = Backbone.Collection.extend({
model : CohortModel,
comparator: "name",
var 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);
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);
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);
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);
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);
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.
}
if (!errorMessage) {
errorMessage = gettext("We've encountered an error. Refresh your browser and then try again.");
/**
* 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();
}
}
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);
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 || {};
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;
},
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);
},
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;
/**
* 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('');
},
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);
},
/**
* 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();
/**
* 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 };
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')
});
});
}
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);
;(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,
......
var edx = edx || {};
(function($, _, Backbone, gettext) {
;(function (define) {
'use strict';
define(['jquery', 'underscore', 'backbone', 'gettext'], function($, _, Backbone, gettext) {
edx.groups = edx.groups || {};
edx.groups.CourseCohortSettingsNotificationView = Backbone.View.extend({
initialize: function(options) {
this.template = _.template($('#cohort-state-tpl').text());
this.cohortEnabled = options.cohortEnabled;
},
var 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);
......@@ -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']
......
......@@ -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',
......
<%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_
</div>
<%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 []
%>
<script type="text/javascript">
$(document).ready(function() {
var cohortUserPartitionId = ${cohorted_user_partition.id if cohorted_user_partition else 'null'},
contentGroups = [
% for content_group in content_groups:
new edx.groups.ContentGroupModel({
id: ${content_group.id},
name: "${content_group.name | h}",
user_partition_id: cohortUserPartitionId
}),
% endfor
];
(function (require) {
require(['js/groups/views/cohorts_dashboard_factory'], function (CohortsFactory) {
CohortsFactory(contentGroups, '${get_studio_url(course, 'group_configurations') | h}');
});
}).call(this, require || RequireJS.require);
});
</script>
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}');
</%static:require_module>
</%block>
<div class="cohort-state-message"></div>
......@@ -56,22 +56,9 @@ from django.core.urlresolvers import reverse
<%static:js group='application'/>
## Backbone classes declared explicitly until RequireJS is supported
<script type="text/javascript" src="${static.url('js/instructor_dashboard/cohort_management.js')}"></script>
<script type="text/javascript" src="${static.url('js/models/notification.js')}"></script>
<script type="text/javascript" src="${static.url('js/views/notification.js')}"></script>
<script type="text/javascript" src="${static.url('js/views/file_uploader.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/models/cohort.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/models/content_group.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/models/course_cohort_settings.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/collections/cohort.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/course_cohort_settings_notification.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/models/cohort_discussions.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohort_discussions.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohort_discussions_course_wide.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohort_discussions_inline.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohort_form.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohort_editor.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohorts.js')}"></script>
<script type="text/javascript" src="${static.url('js/utils/animation.js')}"></script>
</%block>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment