diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index a3862ff21a..f9d007c62e 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -28,9 +28,6 @@ LMS: Student Notes: Toggle single note visibility. TNL-660
LMS: Student Notes: Add Notes page. TNL-797
LMS: Student Notes: Add possibility to add/edit/remove notes. TNL-655
-=======
-LMS: Extend preview to support cohorted courseware. TNL-651
->>>>>>> Extend preview to support cohorted courseware
Platform: Add group_access field to all xblocks. TNL-670
diff --git a/cms/djangoapps/models/settings/course_metadata.py b/cms/djangoapps/models/settings/course_metadata.py
index 23320d1580..1e3a3082f7 100644
--- a/cms/djangoapps/models/settings/course_metadata.py
+++ b/cms/djangoapps/models/settings/course_metadata.py
@@ -28,7 +28,6 @@ class CourseMetadata(object):
'graded',
'hide_from_toc',
'pdf_textbooks',
- 'user_partitions',
'name', # from xblock
'tags', # from xblock
'visible_to_staff_only',
diff --git a/common/test/acceptance/pages/lms/instructor_dashboard.py b/common/test/acceptance/pages/lms/instructor_dashboard.py
index 5b251c7140..963921778b 100644
--- a/common/test/acceptance/pages/lms/instructor_dashboard.py
+++ b/common/test/acceptance/pages/lms/instructor_dashboard.py
@@ -153,7 +153,7 @@ class MembershipPageCohortManagementSection(PageObject):
Adds a new manual cohort with the specified name.
"""
self.q(css=self._bounded_selector("div.cohort-management-nav .action-create")).first.click()
- textinput = self.q(css=self._bounded_selector("#cohort-create-name")).results[0]
+ textinput = self.q(css=self._bounded_selector("#cohort-name")).results[0]
textinput.send_keys(cohort_name)
self.q(css=self._bounded_selector("div.form-actions .action-save")).first.click()
diff --git a/common/test/acceptance/tests/discussion/helpers.py b/common/test/acceptance/tests/discussion/helpers.py
index b38a9a36a0..41f83624d9 100644
--- a/common/test/acceptance/tests/discussion/helpers.py
+++ b/common/test/acceptance/tests/discussion/helpers.py
@@ -3,6 +3,7 @@ Helper functions and classes for discussion tests.
"""
from uuid import uuid4
+import json
from ...fixtures.discussion import (
SingleThreadViewFixture,
@@ -68,11 +69,11 @@ class CohortTestMixin(object):
"""
Adds a cohort group by name, returning the ID for the group.
"""
- url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + '/cohorts/add'
- data = {"name": cohort_name}
+ url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + '/cohorts/'
+ data = json.dumps({"name": cohort_name})
response = course_fixture.session.post(url, data=data, headers=course_fixture.headers)
self.assertTrue(response.ok, "Failed to create cohort")
- return response.json()['cohort']['id']
+ return response.json()['id']
def add_user_to_cohort(self, course_fixture, username, cohort_id):
"""
diff --git a/lms/static/js/groups/models/content_group.js b/lms/static/js/groups/models/content_group.js
new file mode 100644
index 0000000000..d52abe4b8e
--- /dev/null
+++ b/lms/static/js/groups/models/content_group.js
@@ -0,0 +1,14 @@
+var edx = edx || {};
+
+(function(Backbone) {
+ 'use strict';
+
+ edx.groups = edx.groups || {};
+
+ edx.groups.ContentGroupModel = Backbone.Model.extend({
+ idAttribute: 'id',
+ defaults: {
+ name: ''
+ }
+ });
+}).call(this, Backbone);
diff --git a/lms/static/js/groups/views/cohort_editor.js b/lms/static/js/groups/views/cohort_editor.js
index c38af29d14..6b808a1745 100644
--- a/lms/static/js/groups/views/cohort_editor.js
+++ b/lms/static/js/groups/views/cohort_editor.js
@@ -1,18 +1,22 @@
var edx = edx || {};
-(function(Backbone, _, $, gettext, ngettext, interpolate_text, NotificationModel, NotificationView) {
+(function(Backbone, _, $, gettext, ngettext, interpolate_text, CohortFormView, NotificationModel, NotificationView) {
'use strict';
edx.groups = edx.groups || {};
edx.groups.CohortEditorView = Backbone.View.extend({
events : {
- "submit .cohort-management-group-add-form": "addStudents"
+ 'click .wrapper-tabs .tab': 'selectTab',
+ 'click .tab-content-settings .action-save': 'saveSettings',
+ 'submit .cohort-management-group-add-form': 'addStudents'
},
initialize: function(options) {
this.template = _.template($('#cohort-editor-tpl').text());
this.cohorts = options.cohorts;
+ this.cohortUserPartitionId = options.cohortUserPartitionId;
+ this.contentGroups = options.contentGroups;
this.advanced_settings_url = options.advanced_settings_url;
},
@@ -24,11 +28,35 @@ var edx = edx || {};
render: function() {
this.$el.html(this.template({
cohort: this.model,
+ cohortUserPartitionId: this.cohortUserPartitionId,
+ contentGroups: this.contentGroups,
advanced_settings_url: this.advanced_settings_url
}));
+ this.cohortFormView = new CohortFormView({
+ model: this.model,
+ cohortUserPartitionId: this.cohortUserPartitionId,
+ contentGroups: this.contentGroups
+ });
+ this.cohortFormView.render();
+ this.$('.tab-content-settings').append(this.cohortFormView.$el);
return this;
},
+ selectTab: function(event) {
+ var tabElement = $(event.currentTarget),
+ tabName = tabElement.data('tab');
+ event.preventDefault();
+ this.$('.wrapper-tabs .tab').removeClass('is-selected');
+ tabElement.addClass('is-selected');
+ this.$('.tab-content').addClass('is-hidden');
+ this.$('.tab-content-' + tabName).removeClass('is-hidden');
+ },
+
+ saveSettings: function(event) {
+ event.preventDefault();
+ this.cohortFormView.saveForm();
+ },
+
setCohort: function(cohort) {
this.model = cohort;
this.render();
@@ -208,4 +236,5 @@ var edx = edx || {};
}
}
});
-}).call(this, Backbone, _, $, gettext, ngettext, interpolate_text, NotificationModel, NotificationView);
+}).call(this, Backbone, _, $, gettext, ngettext, interpolate_text, edx.groups.CohortFormView,
+ NotificationModel, NotificationView);
diff --git a/lms/static/js/groups/views/cohort_form.js b/lms/static/js/groups/views/cohort_form.js
new file mode 100644
index 0000000000..be67affc53
--- /dev/null
+++ b/lms/static/js/groups/views/cohort_form.js
@@ -0,0 +1,128 @@
+var edx = edx || {};
+
+(function($, _, Backbone, gettext, interpolate_text, CohortModel, NotificationModel, NotificationView) {
+ 'use strict';
+
+ edx.groups = edx.groups || {};
+
+ edx.groups.CohortFormView = Backbone.View.extend({
+ events : {
+ 'change .cohort-management-details-association-course input': 'onRadioButtonChange',
+ 'change .input-cohort-group-association': 'onGroupAssociationChange',
+ 'click .tab-content-settings .action-save': 'saveSettings',
+ 'submit .cohort-management-group-add-form': 'addStudents'
+ },
+
+ initialize: function(options) {
+ this.template = _.template($('#cohort-form-tpl').text());
+ this.cohortUserPartitionId = options.cohortUserPartitionId;
+ this.contentGroups = options.contentGroups;
+ },
+
+ showNotification: function(options, beforeElement) {
+ var model = new NotificationModel(options);
+ this.removeNotification();
+ this.notification = new NotificationView({
+ model: model
+ });
+ this.notification.render();
+ if (!beforeElement) {
+ beforeElement = this.$('.cohort-management-group');
+ }
+ beforeElement.before(this.notification.$el);
+ },
+
+ removeNotification: function() {
+ if (this.notification) {
+ this.notification.remove();
+ }
+ },
+
+ render: function() {
+ this.$el.html(this.template({
+ cohort: this.model,
+ contentGroups: this.contentGroups
+ }));
+ return this;
+ },
+
+ 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 ('Choose a content group to associate').
+ this.$('.input-cohort-group-association').val('None');
+ }
+ },
+
+ onGroupAssociationChange: function(event) {
+ // Since the user has chosen a content group, click the 'Yes' button too
+ this.$('.cohort-management-details-association-course .radio-yes').click();
+ },
+
+ getSelectedGroupId: function() {
+ var selectValue = this.$('.input-cohort-group-association').val();
+ if (!this.$('.radio-yes').prop('checked') || selectValue === 'None') {
+ return null;
+ }
+ return parseInt(selectValue);
+ },
+
+ getUpdatedCohortName: function() {
+ var cohortName = this.$('.cohort-name').val();
+ return cohortName ? cohortName.trim() : this.model.get('name');
+ },
+
+ saveForm: function() {
+ var self = this,
+ cohort = this.model,
+ saveOperation = $.Deferred(),
+ cohortName, groupId, showMessage, showAddError;
+ this.removeNotification();
+ showMessage = function(message, type) {
+ self.showNotification(
+ {type: type || 'confirmation', title: message},
+ self.$('.form-fields')
+ );
+ };
+ showAddError = function(message, type) {
+ showMessage(message, 'error');
+ };
+ cohortName = this.getUpdatedCohortName();
+ if (cohortName.length === 0) {
+ showAddError(gettext('Please enter a name for your new cohort group.'));
+ saveOperation.reject();
+ } else {
+ groupId = this.getSelectedGroupId();
+ cohort.save(
+ {name: cohortName, user_partition_id: this.cohortUserPartitionId, group_id: groupId},
+ {patch: true}
+ ).done(function(result) {
+ if (!result.error) {
+ cohort.id = result.id;
+ showMessage(gettext('Saved cohort group.'));
+ saveOperation.resolve();
+ } else {
+ showAddError(result.error);
+ saveOperation.reject();
+ }
+ }).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. Please refresh your browser and then try again.");
+ }
+ showAddError(errorMessage);
+ saveOperation.reject();
+ });
+ }
+ return saveOperation.promise();
+ }
+ });
+}).call(this, $, _, Backbone, gettext, interpolate_text, edx.groups.CohortModel, NotificationModel, NotificationView);
diff --git a/lms/static/js/groups/views/cohorts.js b/lms/static/js/groups/views/cohorts.js
index 12cdf91978..d5f02b2c6c 100644
--- a/lms/static/js/groups/views/cohorts.js
+++ b/lms/static/js/groups/views/cohorts.js
@@ -1,6 +1,6 @@
var edx = edx || {};
-(function($, _, Backbone, gettext, interpolate_text, CohortEditorView,
+(function($, _, Backbone, gettext, interpolate_text, CohortModel, CohortEditorView, CohortFormView,
NotificationModel, NotificationView, FileUploaderView) {
'use strict';
@@ -13,8 +13,8 @@ var edx = edx || {};
events : {
'change .cohort-select': 'onCohortSelected',
'click .action-create': 'showAddCohortForm',
- 'click .action-cancel': 'cancelAddCohortForm',
- 'click .action-save': 'saveAddCohortForm',
+ 'click .cohort-management-add-modal .action-save': 'saveAddCohortForm',
+ 'click .cohort-management-add-modal .action-cancel': 'cancelAddCohortForm',
'click .link-cross-reference': 'showSection',
'click .toggle-cohort-management-secondary': 'showCsvUpload'
},
@@ -24,9 +24,10 @@ var edx = edx || {};
this.template = _.template($('#cohorts-tpl').text());
this.selectorTemplate = _.template($('#cohort-selector-tpl').text());
- this.addCohortFormTemplate = _.template($('#add-cohort-form-tpl').text());
this.advanced_settings_url = options.advanced_settings_url;
this.upload_cohorts_csv_url = options.upload_cohorts_csv_url;
+ this.cohortUserPartitionId = options.cohortUserPartitionId;
+ this.contentGroups = options.contentGroups;
model.on('sync', this.onSync, this);
// Update cohort counts when the user clicks back on the membership tab
@@ -52,13 +53,17 @@ var edx = edx || {};
}));
},
- onSync: function() {
+ 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');
+ additionalCohortControlElement = this.$('.wrapper-cohort-supplemental'),
+ isModelUpdate = options && options.patch && response.hasOwnProperty('user_partition_id');
this.hideAddCohortForm();
- if (hasCohorts) {
+ 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);
@@ -99,6 +104,8 @@ var edx = edx || {};
el: this.$('.cohort-management-group'),
model: cohort,
cohorts: this.model,
+ cohortUserPartitionId: this.cohortUserPartitionId,
+ contentGroups: this.contentGroups,
advanced_settings_url: this.advanced_settings_url
});
this.editor.render();
@@ -122,21 +129,32 @@ var edx = edx || {};
if (this.notification) {
this.notification.remove();
}
+ if (this.cohortFormView) {
+ this.cohortFormView.removeNotification();
+ }
},
showAddCohortForm: function(event) {
+ var newCohort;
event.preventDefault();
this.removeNotification();
- this.addCohortForm = $(this.addCohortFormTemplate({}));
- this.addCohortForm.insertAfter(this.$('.cohort-management-nav'));
+ newCohort = new CohortModel();
+ newCohort.url = this.model.url;
+ this.cohortFormView = new CohortFormView({
+ model: newCohort,
+ cohortUserPartitionId: this.cohortUserPartitionId,
+ contentGroups: this.contentGroups
+ });
+ this.cohortFormView.render();
+ this.$('.cohort-management-add-modal').append(this.cohortFormView.$el);
this.setCohortEditorVisibility(false);
},
hideAddCohortForm: function() {
this.setCohortEditorVisibility(true);
- if (this.addCohortForm) {
- this.addCohortForm.remove();
- this.addCohortForm = null;
+ if (this.cohortFormView) {
+ this.cohortFormView.remove();
+ this.cohortFormView = null;
}
},
@@ -151,42 +169,23 @@ var edx = edx || {};
},
saveAddCohortForm: function(event) {
- event.preventDefault();
var self = this,
- showAddError,
- cohortName = this.$('.cohort-create-name').val().trim();
- showAddError = function(message) {
- self.showNotification(
- {type: 'error', title: message},
- self.$('.cohort-management-create-form-name label')
- );
- };
+ newCohort = this.cohortFormView.model;
+ event.preventDefault();
this.removeNotification();
- if (cohortName.length > 0) {
- $.post(
- this.model.url + '/add',
- {name: cohortName}
- ).done(function(result) {
- if (result.success) {
- self.lastSelectedCohortId = result.cohort.id;
- self.model.fetch().done(function() {
- self.showNotification({
- type: 'confirmation',
- title: interpolate_text(
- gettext('The {cohortGroupName} cohort group has been created. You can manually add students to this group below.'),
- {cohortGroupName: cohortName}
- )
- });
- });
- } else {
- showAddError(result.msg);
- }
- }).fail(function() {
- showAddError(gettext("We've encountered an error. Please refresh your browser and then try again."));
+ 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 group has been created. You can manually add students to this group below.'),
+ {cohortGroupName: newCohort.get('name')}
+ )
+ });
});
- } else {
- showAddError(gettext('Please enter a name for your new cohort group.'));
- }
+ });
},
cancelAddCohortForm: function(event) {
@@ -234,5 +233,5 @@ var edx = edx || {};
return ".instructor-nav .nav-item a[data-section='" + section + "']";
}
});
-}).call(this, $, _, Backbone, gettext, interpolate_text, edx.groups.CohortEditorView,
- NotificationModel, NotificationView, FileUploaderView);
+}).call(this, $, _, Backbone, gettext, interpolate_text, edx.groups.CohortModel, edx.groups.CohortEditorView,
+ edx.groups.CohortFormView, NotificationModel, NotificationView, FileUploaderView);
diff --git a/lms/static/js/spec/groups/views/cohorts_spec.js b/lms/static/js/spec/groups/views/cohorts_spec.js
index a592e0b5f3..cf9484599e 100644
--- a/lms/static/js/spec/groups/views/cohorts_spec.js
+++ b/lms/static/js/spec/groups/views/cohorts_spec.js
@@ -1,16 +1,21 @@
define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpers/template_helpers',
- 'js/groups/views/cohorts', 'js/groups/collections/cohort', 'string_utils'],
- function (Backbone, $, AjaxHelpers, TemplateHelpers, CohortsView, CohortCollection) {
+ 'js/groups/views/cohorts', 'js/groups/collections/cohort', 'js/groups/models/content_group'],
+ function (Backbone, $, AjaxHelpers, TemplateHelpers, CohortsView, CohortCollection, ContentGroupModel) {
+ 'use strict';
+
describe("Cohorts View", function () {
var catLoversInitialCount = 123, dogLoversInitialCount = 456, unknownUserMessage,
- createMockCohort, createMockCohorts, createCohortsView, cohortsView, requests, respondToRefresh,
- verifyMessage, verifyNoMessage, verifyDetailedMessage, verifyHeader;
+ createMockCohort, createMockCohorts, createMockContentGroups, createCohortsView, cohortsView,
+ requests, respondToRefresh, verifyMessage, verifyNoMessage, verifyDetailedMessage, verifyHeader,
+ expectCohortAddRequest, getAddModal, selectContentGroup, clearContentGroup;
- createMockCohort = function (name, id, user_count) {
+ createMockCohort = function (name, id, userCount, groupId, userPartitionId) {
return {
id: id || 1,
name: name,
- user_count: user_count || 0
+ user_count: userCount || 0,
+ group_id: groupId,
+ user_partition_id: userPartitionId
};
};
@@ -23,17 +28,29 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
};
};
- createCohortsView = function (test, initialCohortID, initialCohorts) {
- var cohorts = new CohortCollection(initialCohorts || createMockCohorts(), {parse: true});
- cohorts.url = '/mock_service';
+ createMockContentGroups = function () {
+ return [
+ new ContentGroupModel({id: 0, name: 'Dog Content'}),
+ new ContentGroupModel({id: 1, name: 'Cat Content'})
+ ];
+ };
+
+ createCohortsView = function (test, options) {
+ var cohortsJson, cohorts, contentGroups;
+ options = options || {};
+ cohortsJson = options.cohorts ? {cohorts: options.cohorts} : createMockCohorts();
+ cohorts = new CohortCollection(cohortsJson, {parse: true});
+ contentGroups = options.contentGroups || createMockContentGroups();
+ cohorts.url = '/mock_service/cohorts';
requests = AjaxHelpers.requests(test);
cohortsView = new CohortsView({
model: cohorts,
+ contentGroups: contentGroups,
upload_cohorts_csv_url: "http://upload-csv-file-url/"
});
cohortsView.render();
- if (initialCohortID) {
- cohortsView.$('.cohort-select').val(initialCohortID.toString()).change();
+ if (options && options.selectCohort) {
+ cohortsView.$('.cohort-select').val(options.selectCohort.toString()).change();
}
};
@@ -41,6 +58,33 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
AjaxHelpers.respondWithJson(requests, createMockCohorts(catCount, dogCount));
};
+ expectCohortAddRequest = function(name, group_id) {
+ AjaxHelpers.expectJsonRequest(
+ requests, 'POST', '/mock_service/cohorts',
+ {
+ name: name,
+ user_count: 0,
+ assignment_type: '',
+ group_id: group_id
+ }
+ );
+ };
+
+ getAddModal = function() {
+ return cohortsView.$('.cohort-management-add-modal');
+ };
+
+ selectContentGroup = function(values) {
+ cohortsView.$('.radio-yes').prop('checked', true).change();
+ cohortsView.$('.input-cohort-group-association').val(values).change();
+ };
+
+ clearContentGroup = function() {
+ cohortsView.$('.radio-no').prop('checked', true).change();
+ expect(cohortsView.$('.radio-yes').prop('checked')).toBeFalsy();
+ expect(cohortsView.$('.input-cohort-group-association').val()).toBe('None');
+ };
+
verifyMessage = function(expectedTitle, expectedMessageType, expectedAction, hasDetails) {
expect(cohortsView.$('.message-title').text().trim()).toBe(expectedTitle);
expect(cohortsView.$('div.message')).toHaveClass('message-' + expectedMessageType);
@@ -94,7 +138,7 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
beforeEach(function () {
setFixtures('
');
TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/cohorts');
- TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/add-cohort-form');
+ TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/cohort-form');
TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/cohort-selector');
TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/cohort-editor');
TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/notification');
@@ -102,7 +146,7 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
});
it("Show an error if no cohorts are defined", function() {
- createCohortsView(this, null, { cohorts: [] });
+ createCohortsView(this, {cohorts: []});
verifyMessage(
'You currently have no cohort groups configured',
'warning',
@@ -114,14 +158,42 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
});
it("Syncs data when membership tab is clicked", function() {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
verifyHeader(1, 'Cat Lovers', catLoversInitialCount);
$(cohortsView.getSectionCss("membership")).click();
- AjaxHelpers.expectRequest(requests, 'GET', '/mock_service');
+ AjaxHelpers.expectRequest(requests, 'GET', '/mock_service/cohorts');
respondToRefresh(1001, 2);
verifyHeader(1, 'Cat Lovers', 1001);
});
+ it('can upload a CSV of cohort assignments if a cohort exists', function () {
+ var uploadCsvToggle, fileUploadForm, fileUploadFormCss='#file-upload-form';
+
+ createCohortsView(this);
+
+ // Should see the control to toggle CSV file upload.
+ expect(cohortsView.$('.wrapper-cohort-supplemental')).not.toHaveClass('is-hidden');
+ // But upload form should not be visible until toggle is clicked.
+ expect(cohortsView.$(fileUploadFormCss).length).toBe(0);
+ uploadCsvToggle = cohortsView.$('.toggle-cohort-management-secondary');
+ expect(uploadCsvToggle.text()).
+ toContain('Assign students to cohort groups by uploading a CSV file');
+ uploadCsvToggle.click();
+ // After toggle is clicked, it should be hidden.
+ expect(uploadCsvToggle).toHaveClass('is-hidden');
+
+ fileUploadForm = cohortsView.$(fileUploadFormCss);
+ expect(fileUploadForm.length).toBe(1);
+ cohortsView.$(fileUploadForm).fileupload('add', {files: [{name: 'upload_file.txt'}]});
+ cohortsView.$('.submit-file-button').click();
+
+ // No file will actually be uploaded because "uploaded_file.txt" doesn't actually exist.
+ AjaxHelpers.expectRequest(requests, 'POST', "http://upload-csv-file-url/", new FormData());
+ AjaxHelpers.respondWithJson(requests, {});
+ expect(cohortsView.$('.file-upload-form-result .message-confirmation .message-title').text().trim())
+ .toBe("Your file 'upload_file.txt' has been uploaded. Please allow a few minutes for processing.");
+ });
+
describe("Cohort Selector", function () {
it('has no initial selection', function () {
createCohortsView(this);
@@ -129,63 +201,57 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
expect(cohortsView.$('.cohort-management-group-header .title-value').text()).toBe('');
});
- it('can upload a CSV of cohort assignments if a cohort exists', function () {
- var uploadCsvToggle, fileUploadForm, fileUploadFormCss='#file-upload-form';
-
- createCohortsView(this);
-
- // Should see the control to toggle CSV file upload.
- expect(cohortsView.$('.wrapper-cohort-supplemental')).not.toHaveClass('is-hidden');
- // But upload form should not be visible until toggle is clicked.
- expect(cohortsView.$(fileUploadFormCss).length).toBe(0);
- uploadCsvToggle = cohortsView.$('.toggle-cohort-management-secondary');
- expect(uploadCsvToggle.text()).
- toContain('Assign students to cohort groups by uploading a CSV file');
- uploadCsvToggle.click();
- // After toggle is clicked, it should be hidden.
- expect(uploadCsvToggle).toHaveClass('is-hidden');
-
- fileUploadForm = cohortsView.$(fileUploadFormCss);
- expect(fileUploadForm.length).toBe(1);
- cohortsView.$(fileUploadForm).fileupload('add', {files: [{name: 'upload_file.txt'}]});
- cohortsView.$('.submit-file-button').click();
-
- // No file will actually be uploaded because "uploaded_file.txt" doesn't actually exist.
- AjaxHelpers.expectRequest(requests, 'POST', "http://upload-csv-file-url/", new FormData());
- AjaxHelpers.respondWithJson(requests, {});
- expect(cohortsView.$('.file-upload-form-result .message-confirmation .message-title').text().trim())
- .toBe("Your file 'upload_file.txt' has been uploaded. Please allow a few minutes for processing.");
- });
-
it('can select a cohort', function () {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
verifyHeader(1, 'Cat Lovers', catLoversInitialCount);
});
it('can switch cohort', function () {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
cohortsView.$('.cohort-select').val("2").change();
verifyHeader(2, 'Dog Lovers', dogLoversInitialCount);
});
});
+ describe("Cohort Editor Tab Panel", function () {
+ it("initially selects the Manage Students tab", function () {
+ createCohortsView(this, {selectCohort: 1});
+ expect(cohortsView.$('.tab-manage_students')).toHaveClass('is-selected');
+ expect(cohortsView.$('.tab-settings')).not.toHaveClass('is-selected');
+ expect(cohortsView.$('.tab-content-manage_students')).not.toHaveClass('is-hidden');
+ expect(cohortsView.$('.tab-content-settings')).toHaveClass('is-hidden');
+ });
+
+ it("can select the Settings tab", function () {
+ createCohortsView(this, {selectCohort: 1});
+ cohortsView.$('.tab-settings a').click();
+ expect(cohortsView.$('.tab-manage_students')).not.toHaveClass('is-selected');
+ expect(cohortsView.$('.tab-settings')).toHaveClass('is-selected');
+ expect(cohortsView.$('.tab-content-manage_students')).toHaveClass('is-hidden');
+ expect(cohortsView.$('.tab-content-settings')).not.toHaveClass('is-hidden');
+ });
+ });
+
describe("Add Cohorts Form", function () {
var defaultCohortName = 'New Cohort';
it("can add a cohort", function() {
- createCohortsView(this, null, { cohorts: [] });
+ var contentGroupId = 0;
+ createCohortsView(this, {cohorts: []});
cohortsView.$('.action-create').click();
- expect(cohortsView.$('.cohort-management-create-form').length).toBe(1);
+ expect(cohortsView.$('.cohort-management-settings-form').length).toBe(1);
expect(cohortsView.$('.cohort-management-nav')).toHaveClass('is-disabled');
expect(cohortsView.$('.cohort-management-group')).toHaveClass('is-hidden');
- cohortsView.$('.cohort-create-name').val(defaultCohortName);
+ cohortsView.$('.cohort-name').val(defaultCohortName);
+ selectContentGroup(contentGroupId);
cohortsView.$('.action-save').click();
- AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/add', 'name=New+Cohort');
+ expectCohortAddRequest(defaultCohortName, contentGroupId);
AjaxHelpers.respondWithJson(
requests,
{
- success: true,
- cohort: { id: 1, name: defaultCohortName }
+ id: 1,
+ name: defaultCohortName,
+ group_id: contentGroupId
}
);
AjaxHelpers.respondWithJson(
@@ -200,75 +266,60 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
verifyHeader(1, defaultCohortName, 0);
expect(cohortsView.$('.cohort-management-nav')).not.toHaveClass('is-disabled');
expect(cohortsView.$('.cohort-management-group')).not.toHaveClass('is-hidden');
- expect(cohortsView.$('.cohort-management-create-form').length).toBe(0);
+ expect(getAddModal().find('.cohort-management-settings-form').length).toBe(0);
});
it("trims off whitespace before adding a cohort", function() {
createCohortsView(this);
cohortsView.$('.action-create').click();
- cohortsView.$('.cohort-create-name').val(' New Cohort ');
+ cohortsView.$('.cohort-name').val(' New Cohort ');
cohortsView.$('.action-save').click();
- AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/add', 'name=New+Cohort');
+ expectCohortAddRequest('New Cohort', null);
});
it("does not allow a blank cohort name to be submitted", function() {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
cohortsView.$('.action-create').click();
- expect(cohortsView.$('.cohort-management-create-form').length).toBe(1);
- cohortsView.$('.cohort-create-name').val('');
+ expect(getAddModal().find('.cohort-management-settings-form').length).toBe(1);
+ cohortsView.$('.cohort-name').val('');
expect(cohortsView.$('.cohort-management-nav')).toHaveClass('is-disabled');
- cohortsView.$('.action-save').click();
+ getAddModal().find('.action-save').click();
expect(requests.length).toBe(0);
verifyMessage('Please enter a name for your new cohort group.', 'error');
});
- it("shows a message when adding a cohort throws a server error", function() {
- createCohortsView(this, 1);
+ it("shows a message when adding a cohort returns a server error", function() {
+ var addModal;
+ createCohortsView(this, {selectCohort: 1});
cohortsView.$('.action-create').click();
- expect(cohortsView.$('.cohort-management-create-form').length).toBe(1);
- cohortsView.$('.cohort-create-name').val(defaultCohortName);
- cohortsView.$('.action-save').click();
- AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/add', 'name=New+Cohort');
- AjaxHelpers.respondWithError(requests);
+ addModal = getAddModal();
+ expect(addModal.find('.cohort-management-settings-form').length).toBe(1);
+ addModal.find('.cohort-name').val(defaultCohortName);
+ addModal.find('.action-save').click();
+ AjaxHelpers.respondWithError(requests, 400, {
+ error: 'You cannot add two cohorts with the same name'
+ });
verifyHeader(1, 'Cat Lovers', catLoversInitialCount);
verifyMessage(
- "We've encountered an error. Please refresh your browser and then try again.",
+ 'You cannot add two cohorts with the same name',
'error'
);
});
- it("shows a server message if adding a cohort fails", function() {
- createCohortsView(this, 1);
- cohortsView.$('.action-create').click();
- expect(cohortsView.$('.cohort-management-create-form').length).toBe(1);
- cohortsView.$('.cohort-create-name').val('Cat Lovers');
- cohortsView.$('.action-save').click();
- AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/add', 'name=Cat+Lovers');
- AjaxHelpers.respondWithJson(
- requests,
- {
- success: false,
- msg: 'You cannot create two cohorts with the same name'
- }
- );
- verifyHeader(1, 'Cat Lovers', catLoversInitialCount);
- verifyMessage('You cannot create two cohorts with the same name', 'error');
- });
-
it("is removed when 'Cancel' is clicked", function() {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
cohortsView.$('.action-create').click();
- expect(cohortsView.$('.cohort-management-create-form').length).toBe(1);
+ expect(getAddModal().find('.cohort-management-settings-form').length).toBe(1);
expect(cohortsView.$('.cohort-management-nav')).toHaveClass('is-disabled');
cohortsView.$('.action-cancel').click();
- expect(cohortsView.$('.cohort-management-create-form').length).toBe(0);
+ expect(getAddModal().find('.cohort-management-settings-form').length).toBe(0);
expect(cohortsView.$('.cohort-management-nav')).not.toHaveClass('is-disabled');
});
it("shows an error if canceled when no cohorts are defined", function() {
- createCohortsView(this, null, { cohorts: [] });
+ createCohortsView(this, {cohorts: []});
cohortsView.$('.action-create').click();
- expect(cohortsView.$('.cohort-management-create-form').length).toBe(1);
+ expect(getAddModal().find('.cohort-management-settings-form').length).toBe(1);
expect(cohortsView.$('.cohort-management-nav')).toHaveClass('is-disabled');
cohortsView.$('.action-cancel').click();
verifyMessage(
@@ -279,11 +330,11 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
});
it("hides any error message when switching to show a cohort", function() {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
// First try to save a blank name to create a message
cohortsView.$('.action-create').click();
- cohortsView.$('.cohort-create-name').val('');
+ cohortsView.$('.cohort-name').val('');
cohortsView.$('.action-save').click();
verifyMessage('Please enter a name for your new cohort group.', 'error');
@@ -294,11 +345,11 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
});
it("hides any error message when canceling the form", function() {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
// First try to save a blank name to create a message
cohortsView.$('.action-create').click();
- cohortsView.$('.cohort-create-name').val('');
+ cohortsView.$('.cohort-name').val('');
cohortsView.$('.action-save').click();
verifyMessage('Please enter a name for your new cohort group.', 'error');
@@ -328,7 +379,7 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
};
it('shows an error when adding with no students specified', function() {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
addStudents(' ');
expect(requests.length).toBe(0);
verifyMessage('Please enter a username or email.', 'error');
@@ -337,9 +388,8 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
it('can add a single student', function() {
var catLoversUpdatedCount = catLoversInitialCount + 1;
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
addStudents('student@sample.com');
- AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/1/add', 'users=student%40sample.com');
respondToAdd({ added: ['student@sample.com'] });
respondToRefresh(catLoversUpdatedCount, dogLoversInitialCount);
verifyHeader(1, 'Cat Lovers', catLoversUpdatedCount);
@@ -348,9 +398,11 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
});
it('shows an error when adding a student that does not exist', function() {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
addStudents('unknown@sample.com');
- AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/1/add', 'users=unknown%40sample.com');
+ AjaxHelpers.expectRequest(
+ requests, 'POST', '/mock_service/cohorts/1/add', 'users=unknown%40sample.com'
+ );
respondToAdd({ unknown: ['unknown@sample.com'] });
respondToRefresh(catLoversInitialCount, dogLoversInitialCount);
verifyHeader(1, 'Cat Lovers', catLoversInitialCount);
@@ -362,11 +414,12 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
it('shows a "view all" button when more than 5 students do not exist', function() {
var sixUsers = 'unknown1@sample.com, unknown2@sample.com, unknown3@sample.com, unknown4@sample.com, unknown5@sample.com, unknown6@sample.com';
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
addStudents(sixUsers);
- AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/1/add',
- 'users=' + sixUsers.replace(/@/g, "%40").replace(/, /g, "%2C+")
+ AjaxHelpers.expectRequest(
+ requests, 'POST', '/mock_service/cohorts/1/add',
+ 'users=' + sixUsers.replace(/@/g, "%40").replace(/, /g, "%2C+")
);
respondToAdd({ unknown: [
'unknown1@sample.com',
@@ -399,10 +452,10 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
it('shows students moved from one cohort to another', function() {
var sixUsers = 'moved1@sample.com, moved2@sample.com, moved3@sample.com, alreadypresent@sample.com';
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
addStudents(sixUsers);
- AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/1/add',
+ AjaxHelpers.expectRequest(requests, 'POST', '/mock_service/cohorts/1/add',
'users=' + sixUsers.replace(/@/g, "%40").replace(/, /g, "%2C+")
);
respondToAdd({
@@ -426,7 +479,7 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
});
it('shows a message when the add fails', function() {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
addStudents('student@sample.com');
AjaxHelpers.respondWithError(requests);
verifyMessage('Error adding students.', 'error');
@@ -434,7 +487,7 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
});
it('clears an error message on subsequent add', function() {
- createCohortsView(this, 1);
+ createCohortsView(this, {selectCohort: 1});
// First verify that an error is shown
addStudents('student@sample.com');
@@ -448,5 +501,105 @@ define(['backbone', 'jquery', 'js/common_helpers/ajax_helpers', 'js/common_helpe
verifyMessage('1 student has been added to this cohort group', 'confirmation');
});
});
+
+ describe("Cohort Settings", function() {
+ describe("Content Group Setting", function() {
+ it("shows a select element with an option for each content group", function () {
+ var options;
+ createCohortsView(this, {selectCohort: 1});
+ cohortsView.$('.tab-settings a').click();
+ options = cohortsView.$('.input-cohort-group-association option');
+ expect(options.length).toBe(3);
+ expect($(options[0]).text().trim()).toBe('Choose a content group to associate');
+ expect($(options[1]).text().trim()).toBe('Cat Content');
+ expect($(options[2]).text().trim()).toBe('Dog Content');
+ });
+
+ it("can select a single content group", function () {
+ createCohortsView(this, {selectCohort: 1});
+ cohortsView.$('.tab-settings a').click();
+
+ // Select the content group with id 1 and verify the radio button was switched to 'Yes'
+ selectContentGroup(0);
+ expect(cohortsView.$('.radio-yes').prop('checked')).toBeTruthy();
+
+ // Click the save button and verify that the correct request is sent
+ cohortsView.$('.action-save').click();
+ AjaxHelpers.expectJsonRequest(
+ requests, 'PATCH', '/mock_service/cohorts/1',
+ {
+ name: 'Cat Lovers',
+ group_id: 0
+ }
+ );
+ AjaxHelpers.respondWithJson(
+ requests,
+ createMockCohort('Cat Lovers', 1, catLoversInitialCount, 0, 0)
+ );
+ verifyMessage('Saved cohort group.', 'confirmation');
+ });
+
+ it("can clear selected content group", function () {
+ createCohortsView(this, {
+ cohorts: [
+ {id: 1, name: 'Cat Lovers', group_id: 0}
+ ],
+ selectCohort: 1
+ });
+ cohortsView.$('.tab-settings a').click();
+ expect(cohortsView.$('.radio-yes').prop('checked')).toBeTruthy();
+ clearContentGroup();
+
+ // Click the save button and verify that the correct request is sent
+ cohortsView.$('.action-save').click();
+ AjaxHelpers.expectJsonRequest(
+ requests, 'PATCH', '/mock_service/cohorts/1',
+ {
+ name: 'Cat Lovers',
+ group_id: null
+ }
+ );
+ AjaxHelpers.respondWithJson(
+ requests,
+ createMockCohort('Cat Lovers', 1, catLoversInitialCount, 0, 0)
+ );
+ verifyMessage('Saved cohort group.', 'confirmation');
+ });
+
+ it("shows a message when the selected content group does not exist", function () {
+ createCohortsView(this, {
+ cohorts: [
+ {id: 1, name: 'Cat Lovers', group_id: 999}
+ ],
+ selectCohort: 1
+ });
+ cohortsView.$('.tab-settings a').click();
+ expect(cohortsView.$('.copy-error').text().trim()).toBe(
+ 'The selected content group has been deleted, you may wish to reassign this cohort group.'
+ );
+ });
+
+ it("shows an error when the save fails", function () {
+ createCohortsView(this, {selectCohort: 1});
+ cohortsView.$('.tab-settings a').click();
+ cohortsView.$('.action-save').click();
+ AjaxHelpers.respondWithError(requests);
+ verifyMessage(
+ 'We\'ve encountered an error. Please refresh your browser and then try again.',
+ 'error'
+ );
+ });
+
+ it("shows an error message when no content groups are specified", function () {
+ createCohortsView(this, {selectCohort: 1, contentGroups: []});
+ cohortsView.$('.tab-settings a').click();
+ expect(
+ cohortsView.$('.msg-inline').text().trim(),
+ 'You haven\'t configured any content groups yet. You need to create a content group ' +
+ 'before you can create assignments.'
+ );
+ });
+ });
+ });
});
});
diff --git a/lms/static/js/spec/main.js b/lms/static/js/spec/main.js
index a0bebd885c..0bf09b003a 100644
--- a/lms/static/js/spec/main.js
+++ b/lms/static/js/spec/main.js
@@ -65,8 +65,10 @@
'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/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',
@@ -284,17 +286,28 @@
exports: 'edx.groups.CohortModel',
deps: ['backbone']
},
+ 'js/groups/models/content_group': {
+ exports: 'edx.groups.ContentGroupModel',
+ deps: ['backbone']
+ },
'js/groups/collections/cohort': {
exports: 'edx.groups.CohortCollection',
deps: ['backbone', 'js/groups/models/cohort']
},
- 'js/groups/views/cohort_editor': {
- exports: 'edx.groups.CohortsEditor',
+ '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: [
diff --git a/lms/static/sass/course/instructor/_cohort-management.scss b/lms/static/sass/course/instructor/_cohort-management.scss
index fbc61004e9..09415054d0 100644
--- a/lms/static/sass/course/instructor/_cohort-management.scss
+++ b/lms/static/sass/course/instructor/_cohort-management.scss
@@ -1,18 +1,3 @@
-.msg {
-
- &.inline {
- @extend %t-copy-sub2;
- display: inline-block;
- margin: 0 0 0 $baseline;
- padding: 0;
- }
-
- &.error {
- @extend %t-copy-sub2;
- color: $error-red;
- }
-}
-
.cohort-management {
.has-option-unavailable { // Given to that have some options that are unavailable
@@ -59,34 +44,40 @@
@include clearfix();
background: $gray-l5;
- .group-header-title {
- padding: $baseline;
- margin-bottom: 0;
- border-bottom: 1px solid $gray-l3;
- text-transform: none;
- letter-spacing: normal;
- }
+ .cohort-manage-group-header {
+ padding: 0;
+ border-bottom: 0;
- .cohort-management-group-setup {
- padding: $baseline;
-
- .cohort-management-group-text {
- display: inline-block;
- width: flex-grid(9);
+ .group-header-title {
+ padding: $baseline;
+ margin-bottom: 0;
+ border-bottom: 1px solid $gray-l3;
+ text-transform: none;
+ letter-spacing: normal;
}
- .cohort-management-group-actions {
- display: inline-block;
- width: flex-grid(3);
- vertical-align: top;
+ .cohort-management-group-setup {
+ padding: $baseline;
- .float-right {
- float: right;
+ .cohort-management-group-text {
+ display: inline-block;
+ width: flex-grid(9);
+ }
+
+ .cohort-management-group-actions {
+ display: inline-block;
+ width: flex-grid(3);
+ vertical-align: top;
+
+ .float-right {
+ float: right;
+ }
}
}
}
- .cohort-management-details {
+ .cohort-management-details,
+ .cohort-management-group-add {
border-top: ($baseline/5) solid $gray-l4;
background: $white;
@@ -149,4 +140,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/lms/static/sass/course/instructor/_instructor_2.scss b/lms/static/sass/course/instructor/_instructor_2.scss
index b7e29989a1..9986772314 100644
--- a/lms/static/sass/course/instructor/_instructor_2.scss
+++ b/lms/static/sass/course/instructor/_instructor_2.scss
@@ -17,7 +17,6 @@
.instructor-dashboard-wrapper-2 {
position: relative;
- // display: table;
.olddash-button-wrapper {
position: absolute;
@@ -56,6 +55,14 @@
}
}
+ // TYPE: inline
+ .msg-inline {
+ @extend %t-copy-sub2;
+ display: inline-block;
+ margin: 0 0 0 $baseline;
+ padding: 0;
+ }
+
// TYPE: warning
.msg-warning {
border-top: 2px solid $warning-color;
@@ -125,16 +132,11 @@
// instructor dashboard 2
// ====================
-section.instructor-dashboard-content-2 {
+.instructor-dashboard-content-2 {
@extend .content;
- // position: relative;
padding: 40px;
width: 100%;
- // .has-event-handler-for-click {
- // border: 1px solid blue;
- // }
-
.wrap-instructor-info {
display: inline;
top: 0;
@@ -222,6 +224,7 @@ section.instructor-dashboard-content-2 {
// messages
.message {
+ margin-top: $baseline;
margin-bottom: $baseline;
display: block;
border-radius: 1px;
@@ -426,6 +429,7 @@ section.instructor-dashboard-content-2 {
}
// view - membership
+// --------------------
.instructor-dashboard-wrapper-2 section.idash-section#membership {
.membership-section {
@@ -538,11 +542,17 @@ section.instructor-dashboard-content-2 {
}
// create or edit cohort group
- .cohort-management-create, .cohort-management-edit {
+ .cohort-management-settings,
+ .cohort-management-edit {
@extend %cohort-management-form;
border: 1px solid $gray-l5;
margin-bottom: $baseline;
+ .message {
+ margin-left: $baseline;
+ margin-right: $baseline;
+ }
+
.form-title {
@extend %t-title5;
@extend %t-weight4;
@@ -551,7 +561,7 @@ section.instructor-dashboard-content-2 {
padding: $baseline;
}
- .form-fields {
+ .form-field {
padding: $baseline;
}
@@ -640,6 +650,9 @@ section.instructor-dashboard-content-2 {
@extend %t-title6;
@extend %t-weight4;
margin-bottom: ($baseline/4);
+ border: none;
+ background: transparent;
+ padding: 0;
}
.form-introduction {
@@ -957,7 +970,148 @@ section.instructor-dashboard-content-2 {
}
}
}
+
+ /*
+ * Begin additional/override styles for cohort management.
+ * Placed for merge, but will need to be cleaned up and
+ * refactored in this stylesheet.
+ */
+
+ .has-other-input-text { // Given to groups which have an 'other' input that appears when needed
+ display: inline-block;
+
+ label {
+ display: inline-block;
+ }
+
+ .input-group-other {
+ display: inline;
+ position: relative;
+ overflow: auto;
+ width: 100%;
+ height: auto;
+ margin: 0 0 0 $baseline;
+ padding: inherit;
+ border: inherit;
+ clip: auto;
+
+ &.is-hidden {
+ display: none;
+ }
+
+ .input-cohort-group-association {
+ display: inline;
+ }
+ }
+ }
+
+ .cohort-management-nav {
+ margin-bottom: $baseline;
+ }
+
+ .cohort-management-settings {
+ @include clearfix();
+ background: $gray-l5;
+
+ .cohort-management-group-header {
+ padding: 0;
+ border-bottom: 0;
+
+ .group-header-title {
+ padding: $baseline;
+ margin-bottom: 0;
+ border-bottom: 1px solid $gray-l3;
+ text-transform: none;
+ letter-spacing: normal;
+ }
+
+ .cohort-management-group-setup {
+ padding: $baseline;
+
+ .cohort-management-group-text {
+ display: inline-block;
+ width: flex-grid(9);
+ }
+
+ .cohort-management-group-actions {
+ display: inline-block;
+ width: flex-grid(3);
+ vertical-align: top;
+ text-align: right;
+ }
+ }
+ }
+
+ .cohort-management-details,
+ .cohort-management-group-add {
+ border-top: ($baseline/5) solid $gray-l4;
+ background: $white;
+
+ .cohort-management-settings {
+ margin-bottom: 0;
+ border-top: 0;
+ background: $white;
+ }
+
+ .cohort-details-name {
+ @extend %t-action1;
+ display: block;
+ width: 100%;
+ padding: ($baseline/2);
+ margin-bottom: ($baseline*2);
+ }
+
+ .cohort-section-header {
+ margin-top: ($baseline*1.5);
+ padding: $baseline 0 ($baseline/2) 0;
+ }
+
+ .cohort-section-header > .form-field {
+ padding-bottom: $baseline;
+ }
+ }
+ }
+
+ .wrapper-tabs { // This applies to the tab-like interface that toggles between the student management and the group settings
+ @extend %ui-no-list;
+ @extend %ui-depth1;
+ position: relative;
+ top: (($baseline/5));
+ padding: 0 $baseline;
+
+ .tab {
+ position: relative;
+ display: inline-block;
+
+ a {
+ display: inline-block;
+ padding: $baseline;
+ -webkit-transition: none;
+ -moz-transition: none;
+ -ms-transition: none;
+ -o-transition: none;
+ transition: none;
+ }
+
+ &.is-selected { // Active or selected tabs () get this class. Also useful for aria stuff if ever implemented in the future.
+
+ a {
+ padding-bottom: ($baseline+($baseline/5));
+ border-style: solid;
+ border-width: ($baseline/5) ($baseline/5) 0 ($baseline/5);
+ border-color: $gray-l4;
+ background: $white;
+ color: inherit;
+ cursor: default;
+ }
+ }
+ }
+ }
}
+/*
+ * End of additions/overrides
+ * Don't forget to refactor.
+ */
// view - student admin
// --------------------
@@ -1771,5 +1925,3 @@ input[name="subject"] {
left: 2em;
right: auto;
}
-
-@import '_cohort-management';
\ No newline at end of file
diff --git a/lms/templates/instructor/instructor_dashboard_2/add-cohort-form.underscore b/lms/templates/instructor/instructor_dashboard_2/add-cohort-form.underscore
deleted file mode 100644
index 3680de44b5..0000000000
--- a/lms/templates/instructor/instructor_dashboard_2/add-cohort-form.underscore
+++ /dev/null
@@ -1,26 +0,0 @@
-
diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort-editor.underscore b/lms/templates/instructor/instructor_dashboard_2/cohort-editor.underscore
index 4bfc997c00..60a39690af 100644
--- a/lms/templates/instructor/instructor_dashboard_2/cohort-editor.underscore
+++ b/lms/templates/instructor/instructor_dashboard_2/cohort-editor.underscore
@@ -1,63 +1,72 @@
-
-
-
-