From 9b28afb7bd90ffa928debf727779c95c6416ae2b Mon Sep 17 00:00:00 2001 From: cahrens Date: Wed, 27 Apr 2016 11:49:13 -0400 Subject: [PATCH] Add messaging when verified track content MVP is enabled. TNL-4393 --- .../instructor/views/instructor_dashboard.py | 3 + .../tests/test_views.py | 72 ++++++++++ .../verified_track_content/views.py | 39 ++++++ lms/static/js/groups/models/cohort.js | 2 +- .../groups/models/verified_track_settings.js | 12 ++ lms/static/js/groups/views/cohorts.js | 36 ++++- .../groups/views/cohorts_dashboard_factory.js | 1 + .../verified_track_settings_notification.js | 80 +++++++++++ .../js/spec/groups/views/cohorts_spec.js | 126 ++++++++++++++++-- lms/static/sass/base/_variables.scss | 2 +- .../sass/course/instructor/_instructor_2.scss | 20 ++- .../cohort-form.underscore | 9 +- .../cohort_management.html | 1 + lms/urls.py | 8 +- 14 files changed, 381 insertions(+), 30 deletions(-) create mode 100644 lms/djangoapps/verified_track_content/tests/test_views.py create mode 100644 lms/djangoapps/verified_track_content/views.py create mode 100644 lms/static/js/groups/models/verified_track_settings.js create mode 100644 lms/static/js/groups/views/verified_track_settings_notification.js diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index bce031e887..950140e012 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -477,6 +477,9 @@ def _section_cohort_management(course, access): 'cohorts_url': reverse('cohorts', kwargs={'course_key_string': unicode(course_key)}), 'upload_cohorts_csv_url': reverse('add_users_to_cohorts', kwargs={'course_id': unicode(course_key)}), 'discussion_topics_url': reverse('cohort_discussion_topics', kwargs={'course_key_string': unicode(course_key)}), + 'verified_track_cohorting_url': reverse( + 'verified_track_cohorting', kwargs={'course_key_string': unicode(course_key)} + ), } return section_data diff --git a/lms/djangoapps/verified_track_content/tests/test_views.py b/lms/djangoapps/verified_track_content/tests/test_views.py new file mode 100644 index 0000000000..25f7e73253 --- /dev/null +++ b/lms/djangoapps/verified_track_content/tests/test_views.py @@ -0,0 +1,72 @@ +""" +Tests for verified track content views. +""" + +import json + +from nose.plugins.attrib import attr +from unittest import skipUnless + +from django.http import Http404 +from django.test.client import RequestFactory +from django.conf import settings + +from student.tests.factories import UserFactory, AdminFactory +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory + +from verified_track_content.models import VerifiedTrackCohortedCourse +from verified_track_content.views import cohorting_settings + + +@attr('shard_2') +@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Tests only valid in LMS') +class CohortingSettingsTestCase(SharedModuleStoreTestCase): + """ + Tests the `cohort_discussion_topics` view. + """ + + @classmethod + def setUpClass(cls): + super(CohortingSettingsTestCase, cls).setUpClass() + cls.course = CourseFactory.create() + + def test_non_staff(self): + """ + Verify that we cannot access cohorting_settings if we're a non-staff user. + """ + request = RequestFactory().get("dummy_url") + request.user = UserFactory() + with self.assertRaises(Http404): + cohorting_settings(request, unicode(self.course.id)) + + def test_cohorting_settings_enabled(self): + """ + Verify that cohorting_settings is working for HTTP GET when verified track cohorting is enabled. + """ + config = VerifiedTrackCohortedCourse.objects.create( + course_key=unicode(self.course.id), enabled=True, verified_cohort_name="Verified Learners" + ) + config.save() + + expected_response = { + "enabled": True, + "verified_cohort_name": "Verified Learners" + } + self._verify_cohort_settings_response(expected_response) + + def test_cohorting_settings_disabled(self): + """ + Verify that cohorting_settings is working for HTTP GET when verified track cohorting is disabled. + """ + expected_response = { + "enabled": False + } + self._verify_cohort_settings_response(expected_response) + + def _verify_cohort_settings_response(self, expected_response): + request = RequestFactory().get("dummy_url") + request.user = AdminFactory() + response = cohorting_settings(request, unicode(self.course.id)) + self.assertEqual(200, response.status_code) + self.assertEqual(expected_response, json.loads(response.content)) diff --git a/lms/djangoapps/verified_track_content/views.py b/lms/djangoapps/verified_track_content/views.py new file mode 100644 index 0000000000..e5d776323b --- /dev/null +++ b/lms/djangoapps/verified_track_content/views.py @@ -0,0 +1,39 @@ +""" +View methods for verified track content. +""" + +from util.json_request import expect_json, JsonResponse +from django.contrib.auth.decorators import login_required + +from opaque_keys.edx.keys import CourseKey +from courseware.courses import get_course_with_access + +from verified_track_content.models import VerifiedTrackCohortedCourse + + +@expect_json +@login_required +def cohorting_settings(request, course_key_string): + """ + The handler for verified track cohorting requests. + This will raise 404 if user is not staff. + + Returns a JSON representation of whether or not the course has verified track cohorting enabled. + The "verified_cohort_name" field will only be present if "enabled" is True. + + Example: + >>> example = { + >>> "enabled": True, + >>> "verified_cohort_name" : "Micromasters" + >>> } + """ + course_key = CourseKey.from_string(course_key_string) + get_course_with_access(request.user, 'staff', course_key) + + settings = {} + verified_track_cohort_enabled = VerifiedTrackCohortedCourse.is_verified_track_cohort_enabled(course_key) + settings['enabled'] = verified_track_cohort_enabled + if verified_track_cohort_enabled: + settings['verified_cohort_name'] = VerifiedTrackCohortedCourse.verified_cohort_name_for_course(course_key) + + return JsonResponse(settings) diff --git a/lms/static/js/groups/models/cohort.js b/lms/static/js/groups/models/cohort.js index 933bf3ccab..7b0ded9e10 100644 --- a/lms/static/js/groups/models/cohort.js +++ b/lms/static/js/groups/models/cohort.js @@ -8,7 +8,7 @@ name: '', user_count: 0, /** - * Indicates how students are added to the cohort. Will be "none" (signifying manual assignment) or + * Indicates how students are added to the cohort. Will be "manual" (signifying manual assignment) or * "random" (indicating students are randomly assigned). */ assignment_type: '', diff --git a/lms/static/js/groups/models/verified_track_settings.js b/lms/static/js/groups/models/verified_track_settings.js new file mode 100644 index 0000000000..2fad6a499c --- /dev/null +++ b/lms/static/js/groups/models/verified_track_settings.js @@ -0,0 +1,12 @@ +;(function (define) { + 'use strict'; + define(['backbone'], function(Backbone) { + var VerifiedTrackSettingsModel = Backbone.Model.extend({ + defaults: { + enabled: false, + verified_cohort_name: '' + } + }); + return VerifiedTrackSettingsModel; + }); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/views/cohorts.js b/lms/static/js/groups/views/cohorts.js index 4ae304a15b..2b680aea45 100644 --- a/lms/static/js/groups/views/cohorts.js +++ b/lms/static/js/groups/views/cohorts.js @@ -1,16 +1,20 @@ ;(function (define) { 'use strict'; - define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/models/cohort', + define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/models/cohort', + 'js/groups/models/verified_track_settings', '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/groups/views/verified_track_settings_notification', 'edx-ui-toolkit/js/utils/html-utils', 'js/views/file_uploader', 'js/models/notification', 'js/views/notification', 'string_utils'], - function($, _, Backbone, gettext, CohortModel, CohortEditorView, CohortFormView, - CourseCohortSettingsNotificationView, InlineDiscussionsView, CourseWideDiscussionsView, HtmlUtils) { + function($, _, Backbone, gettext, CohortModel, VerifiedTrackSettingsModel, CohortEditorView, CohortFormView, + CourseCohortSettingsNotificationView, InlineDiscussionsView, CourseWideDiscussionsView, + VerifiedTrackSettingsNotificationView, HtmlUtils) { var hiddenClass = 'is-hidden', - disabledClass = 'is-disabled'; + disabledClass = 'is-disabled', + enableCohortsSelector = '.cohorts-state'; var CohortsView = Backbone.View.extend({ @@ -49,6 +53,19 @@ cohortsEnabled: this.cohortSettings.get('is_cohorted') })); this.onSync(); + // Don't create this view until the first render is called, as at that point the + // various other models whose state is required to properly view the notification + // will have completed their fetch operations. + if (!this.verifiedTrackSettingsNotificationView) { + var verifiedTrackSettingsModel = new VerifiedTrackSettingsModel(); + verifiedTrackSettingsModel.url = this.context.verifiedTrackCohortingUrl; + verifiedTrackSettingsModel.fetch({ + success: _.bind(this.renderVerifiedTrackSettingsNotificationView, this) + }); + this.verifiedTrackSettingsNotificationView = new VerifiedTrackSettingsNotificationView({ + model: verifiedTrackSettingsModel + }); + } return this; }, @@ -67,6 +84,14 @@ cohortStateMessageNotificationView.render(); }, + renderVerifiedTrackSettingsNotificationView: function() { + if (this.verifiedTrackSettingsNotificationView) { + this.verifiedTrackSettingsNotificationView.validateSettings( + this.getCohortsEnabled(), this.model.models, this.$(enableCohortsSelector) + ); + } + }, + onSync: function(model, response, options) { var selectedCohort = this.lastSelectedCohortId && this.model.get(this.lastSelectedCohortId), hasCohorts = this.model.length > 0, @@ -100,6 +125,7 @@ actionIconClass: 'fa-plus' }); } + this.renderVerifiedTrackSettingsNotificationView(); }, getSelectedCohort: function() { @@ -139,7 +165,7 @@ }, getCohortsEnabled: function() { - return this.$('.cohorts-state').prop('checked'); + return this.$(enableCohortsSelector).prop('checked'); }, showCohortEditor: function(cohort) { diff --git a/lms/static/js/groups/views/cohorts_dashboard_factory.js b/lms/static/js/groups/views/cohorts_dashboard_factory.js index f6f3bb7e1d..c3d36dae82 100644 --- a/lms/static/js/groups/views/cohorts_dashboard_factory.js +++ b/lms/static/js/groups/views/cohorts_dashboard_factory.js @@ -31,6 +31,7 @@ context: { discussionTopicsSettingsModel: discussionTopicsSettings, uploadCohortsCsvUrl: cohortManagementElement.data('upload_cohorts_csv_url'), + verifiedTrackCohortingUrl: cohortManagementElement.data('verified_track_cohorting_url'), studioGroupConfigurationsUrl: studioGroupConfigurationsUrl } }); diff --git a/lms/static/js/groups/views/verified_track_settings_notification.js b/lms/static/js/groups/views/verified_track_settings_notification.js new file mode 100644 index 0000000000..72c4f6440e --- /dev/null +++ b/lms/static/js/groups/views/verified_track_settings_notification.js @@ -0,0 +1,80 @@ +;(function (define) { + 'use strict'; + define(['jquery', 'underscore', 'backbone', 'gettext', 'edx-ui-toolkit/js/utils/string-utils', + 'js/models/notification', 'js/views/notification'], + function ($, _, Backbone, gettext, StringUtils) { + /*global NotificationModel, NotificationView */ + + var VerifiedTrackSettingsNotificationView = Backbone.View.extend({ + + render: function () { + // All rendering is done in validateSettings, which must be called with some additional information. + return this; + }, + + validateSettings: function (isCohorted, cohortCollection, enableCohortsCheckbox) { + if (this.model.get('enabled')) { + var verifiedCohortName = this.model.get('verified_cohort_name'); + if (isCohorted) { + var verifiedCohortExists = false; + $.each(cohortCollection, function (_, cohort) { + if (cohort.get('assignment_type') === 'manual' && + cohort.get('name') === verifiedCohortName) { + verifiedCohortExists = true; + cohort.disableEditingName = true; + } + else { + cohort.disableEditingName = false; + } + } + ); + if (verifiedCohortExists) { + this.showNotification({ + type: 'confirmation', + title: StringUtils.interpolate( + gettext("This course uses automatic cohorting for verified track learners. You cannot disable cohorts, and you cannot rename the manual cohort named '{verifiedCohortName}'. To change the configuration for verified track cohorts, contact your edX partner manager."), // jshint ignore:line + {verifiedCohortName: verifiedCohortName} + ) + }); + + } + else { + this.showNotification({ + type: 'error', + title: StringUtils.interpolate( + gettext("This course has automatic cohorting enabled for verified track learners, but the required cohort does not exist. You must create a manually-assigned cohort named '{verifiedCohortName}' for the feature to work."), // jshint ignore:line + {verifiedCohortName: verifiedCohortName} + ) + }); + } + enableCohortsCheckbox.prop('disabled', true); + } + else { + this.showNotification({ + type: 'error', + title: gettext('This course has automatic cohorting enabled for verified track learners, but cohorts are disabled. You must enable cohorts for the feature to work.') // jshint ignore:line + }); + enableCohortsCheckbox.prop('disabled', false); + } + } + }, + + showNotification: function (options) { + if (this.notification) { + this.notification.remove(); + } + this.notification = new NotificationView({ + model: new NotificationModel(options) + }); + + // It's ugly to reach outside to the cohort-management div, but we want this notification + // message to always be visible (as opposed to using the transient notification area defined + // by cohorts.js). + $('.cohort-management').before(this.notification.$el); + + this.notification.render(); + } + }); + return VerifiedTrackSettingsNotificationView; + }); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/spec/groups/views/cohorts_spec.js b/lms/static/js/spec/groups/views/cohorts_spec.js index 1d52565342..052016d542 100644 --- a/lms/static/js/spec/groups/views/cohorts_spec.js +++ b/lms/static/js/spec/groups/views/cohorts_spec.js @@ -13,12 +13,14 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ describe("Cohorts View", function () { var catLoversInitialCount = 123, dogLoversInitialCount = 456, unknownUserMessage, createMockCohort, createMockCohorts, createMockContentGroups, createMockCohortSettingsJson, - createCohortsView, cohortsView, requests, respondToRefresh, verifyMessage, verifyNoMessage, - verifyDetailedMessage, verifyHeader, expectCohortAddRequest, getAddModal, selectContentGroup, - clearContentGroup, saveFormAndExpectErrors, createMockCohortSettings, MOCK_COHORTED_USER_PARTITION_ID, + createMockVerifiedTrackCohortsJson, flushVerifiedTrackCohortRequests, createCohortsView, + cohortsView, requests, respondToRefresh, verifyMessage, verifyNoMessage, verifyDetailedMessage, + verifyHeader, verifyVerifiedTrackMessage, verifyVerifiedTrackUIUpdates, expectCohortAddRequest, + getAddModal, selectContentGroup, clearContentGroup, + saveFormAndExpectErrors, createMockCohortSettings, MOCK_COHORTED_USER_PARTITION_ID, MOCK_UPLOAD_COHORTS_CSV_URL, MOCK_STUDIO_ADVANCED_SETTINGS_URL, MOCK_STUDIO_GROUP_CONFIGURATIONS_URL, - MOCK_MANUAL_ASSIGNMENT, MOCK_RANDOM_ASSIGNMENT, createMockCohortDiscussionsJson, - createMockCohortDiscussions, showAndAssertDiscussionTopics; + MOCK_VERIFIED_TRACK_COHORTING_URL, MOCK_MANUAL_ASSIGNMENT, MOCK_RANDOM_ASSIGNMENT, + createMockCohortDiscussionsJson, createMockCohortDiscussions, showAndAssertDiscussionTopics; // Selectors var discussionsToggle ='.toggle-cohort-management-discussions', @@ -34,6 +36,7 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ MOCK_UPLOAD_COHORTS_CSV_URL = 'http://upload-csv-file-url/'; MOCK_STUDIO_ADVANCED_SETTINGS_URL = 'http://studio/settings/advanced'; MOCK_STUDIO_GROUP_CONFIGURATIONS_URL = 'http://studio/group_configurations'; + MOCK_VERIFIED_TRACK_COHORTING_URL = 'http://courses/foo/verified_track_content/settings'; createMockCohort = function (name, id, userCount, groupId, userPartitionId, assignmentType) { return { @@ -129,6 +132,18 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ ); }; + createMockVerifiedTrackCohortsJson = function (enabled) { + if (enabled) { + return { + enabled: true, + verified_cohort_name: "Verified Track" + }; + } + else { + return { enabled: false }; + } + }; + createCohortsView = function (test, options) { var cohortsJson, cohorts, contentGroups, cohortSettings, cohortDiscussions; options = options || {}; @@ -151,7 +166,8 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ discussionTopicsSettingsModel: cohortDiscussions, uploadCohortsCsvUrl: MOCK_UPLOAD_COHORTS_CSV_URL, studioAdvancedSettingsUrl: MOCK_STUDIO_ADVANCED_SETTINGS_URL, - studioGroupConfigurationsUrl: MOCK_STUDIO_GROUP_CONFIGURATIONS_URL + studioGroupConfigurationsUrl: MOCK_STUDIO_GROUP_CONFIGURATIONS_URL, + verifiedTrackCohortingUrl: MOCK_VERIFIED_TRACK_COHORTING_URL } }); @@ -159,6 +175,21 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ if (options && options.selectCohort) { cohortsView.$('.cohort-select').val(options.selectCohort.toString()).change(); } + + flushVerifiedTrackCohortRequests(options.enableVerifiedTrackCohorting); + }; + + // Flush out all requests to get verified track cohort information. + // The order relative to other requests is not important to encode, + // and for pre-existing test cases, we don't care about these additional requests. + flushVerifiedTrackCohortRequests = function (enableVerifiedTrackCohorting) { + for (var i = requests.length-1; i >= 0 ; i--) { + if (requests[i].url === MOCK_VERIFIED_TRACK_COHORTING_URL) { + AjaxHelpers.respondWithJson( + requests, createMockVerifiedTrackCohortsJson(enableVerifiedTrackCohorting), i + ); + } + } }; respondToRefresh = function(catCount, dogCount) { @@ -213,6 +244,27 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ expect(cohortsView.$('.message').length).toBe(0); }; + verifyVerifiedTrackMessage = function(type, expectedText) { + if (type) { + expect($('.message').length).toBe(1); + expect($('.message-' + type).length).toBe(1); + expect($('.message-title').text()).toContain(expectedText); + } + else { + expect($('.message').length).toBe(0); + } + }; + + verifyVerifiedTrackUIUpdates = function(enableCohortsCheckbox, disableCohortNameField) { + expect(cohortsView.$('.cohorts-state').prop('disabled')).toBe(enableCohortsCheckbox); + // Select settings tab + if (disableCohortNameField !== undefined) { + cohortsView.$('.cohort-select').val('1').change(); + cohortsView.$('.tab-settings a').click(); + expect(cohortsView.$('.cohort-name').prop('readonly')).toBe(disableCohortNameField); + } + }; + verifyDetailedMessage = function(expectedTitle, expectedMessageType, expectedDetails, expectedAction) { var numDetails = cohortsView.$('.summary-items').children().length; verifyMessage(expectedTitle, expectedMessageType, expectedAction, true); @@ -243,7 +295,7 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ var manualMessage = "Learners are added to this cohort only when you provide their email addresses " + "or usernames on this page."; var randomMessage = "Learners are added to this cohort automatically."; - var message = (assignmentType == MOCK_MANUAL_ASSIGNMENT) ? manualMessage : randomMessage; + var message = (assignmentType === MOCK_MANUAL_ASSIGNMENT) ? manualMessage : randomMessage; expect(header.find('.cohort-management-group-setup .setup-value').text().trim().split('\n')[0]).toBe(message); }; @@ -301,7 +353,9 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ }; beforeEach(function () { - setFixtures('
'); + setFixtures('
' + + '
'); TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/cohorts'); TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/cohort-form'); TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/cohort-selector'); @@ -390,6 +444,53 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ }); }); + describe("Verified Track Cohorting Settings View", function () { + it('displays no message if the feature is disabled', function () { + createCohortsView(this); + verifyVerifiedTrackMessage(false); + verifyVerifiedTrackUIUpdates(false, false); + }); + + it('displays a confirmation if the feature is enabled and a verified track cohort exists', function () { + var cohortName = "Verified Track"; + createCohortsView(this, { + cohorts: [ + { + id: 1, + name: cohortName, + assignment_type: MOCK_MANUAL_ASSIGNMENT, + group_id: 111, + user_partition_id: MOCK_COHORTED_USER_PARTITION_ID + } + ], + enableVerifiedTrackCohorting: true + }); + verifyVerifiedTrackMessage( + "confirmation", "automatic cohorting for verified track learners. You cannot disable cohorts" + ); + verifyVerifiedTrackUIUpdates(true, true); + }); + + it('displays an error if no verified track cohort exists', function () { + createCohortsView(this, {enableVerifiedTrackCohorting: true}); + verifyVerifiedTrackMessage( + "error", "cohorting enabled for verified track learners, but the required cohort does not exist" + ); + verifyVerifiedTrackUIUpdates(true, false); + }); + + it('displays an error if cohorting is disabled', function () { + createCohortsView(this, { + cohortSettings: createMockCohortSettings(false), + enableVerifiedTrackCohorting: true + }); + verifyVerifiedTrackMessage( + "error", "automatic cohorting enabled for verified track learners, but cohorts are disabled" + ); + verifyVerifiedTrackUIUpdates(false); + }); + }); + describe("Course Cohort Settings", function () { it('can enable and disable cohorting', function () { createCohortsView(this, {cohortSettings: createMockCohortSettings(false)}); @@ -441,7 +542,7 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ expect(cohortsView.$('.cohorts-state').prop('checked')).toBeFalsy(); cohortsView.$('.cohorts-state').prop('checked', true).change(); AjaxHelpers.respondWithError(requests, 500); - var expectedTitle = "We've encountered an error. Refresh your browser and then try again." + var expectedTitle = "We've encountered an error. Refresh your browser and then try again."; expect(cohortsView.$('.message-title').text().trim()).toBe(expectedTitle); }); }); @@ -456,7 +557,7 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ assignment_type: assignment_type, group_id: null, user_partition_id: null - } + }; }; createCohortsView(this, { cohorts: [ @@ -520,8 +621,7 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ var assignmentType = 'random'; it("can add a cohort", function() { - var contentGroupId = 0, - contentGroupUserPartitionId = 0; + var contentGroupId = 0; createCohortsView(this, {cohorts: []}); cohortsView.$('.action-create').click(); expect(cohortsView.$('.cohort-management-settings-form').length).toBe(1); @@ -989,7 +1089,7 @@ define(['backbone', 'jquery', 'common/js/spec_helpers/ajax_helpers', 'common/js/ assignment_type: assignment_type, group_id: null, user_partition_id: null - } + }; }; createCohortsView(this, { cohorts: [ diff --git a/lms/static/sass/base/_variables.scss b/lms/static/sass/base/_variables.scss index 4f681edb0a..6c62583c5c 100644 --- a/lms/static/sass/base/_variables.scss +++ b/lms/static/sass/base/_variables.scss @@ -201,7 +201,7 @@ $shadow-d2: rgba($black, 0.6) !default; // system feedback-based colors $error-color: rgb(253, 87, 87) !default; $warning-color: rgb(181,42,103) !default; -$confirm-color: rgb(0, 136, 1) !default; +$confirm-color: rgb(0, 132, 1) !default; $active-color: $blue !default; $highlight-color: rgb(255,255,0) !default; $alert-color: rgb(212, 64, 64) !default; diff --git a/lms/static/sass/course/instructor/_instructor_2.scss b/lms/static/sass/course/instructor/_instructor_2.scss index a23634864f..8b3bea62f8 100644 --- a/lms/static/sass/course/instructor/_instructor_2.scss +++ b/lms/static/sass/course/instructor/_instructor_2.scss @@ -84,11 +84,11 @@ // TYPE: confirm .msg-error { - border-top: 2px solid $error-color; - background: tint($error-color,95%); + border-top: 2px solid $red1; + background: tint($red1, 90%); .copy { - color: $error-color; + color: $red1; } } @@ -247,11 +247,11 @@ // type - error .message-error { - border-top: 2px solid $error-color; - background: tint($error-color,95%); + border-top: 2px solid $red1; + background: tint($red1, 90%); .message-title { - color: $error-color; + color: $red1; } .message-copy { @@ -262,7 +262,7 @@ // type - confirmation .message-confirmation { border-top: 2px solid $confirm-color; - background: tint($confirm-color,95%); + background: tint($confirm-color, 95%); .message-title { color: $confirm-color; @@ -671,6 +671,12 @@ // needed to reset poor input styling input[type="text"] { height: auto; + &.readonly { + background-color: transparent; + padding: 0; + border: none; + box-shadow: none; + } } .input { diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore b/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore index 429afcfbaf..0643d26b3b 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore +++ b/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -25,8 +25,13 @@ <%- gettext('Cohort Name') %> * <%- gettext('(Required Field)')%> - + + " + <% } %> + id="cohort-name" placeholder="<%- placeholder_value %>" required="required" type="text">
<% if (isDefaultCohort) { %> diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort_management.html b/lms/templates/instructor/instructor_dashboard_2/cohort_management.html index 48452a570f..19bf167bbd 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort_management.html +++ b/lms/templates/instructor/instructor_dashboard_2/cohort_management.html @@ -15,6 +15,7 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_ data-upload_cohorts_csv_url="${section_data['upload_cohorts_csv_url']}" data-course_cohort_settings_url="${section_data['course_cohort_settings_url']}" data-discussion-topics-url="${section_data['discussion_topics_url']}" + data-verified_track_cohorting_url="${section_data['verified_track_cohorting_url']}" > diff --git a/lms/urls.py b/lms/urls.py index f3db4952ce..b1b3d54853 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -611,7 +611,13 @@ urlpatterns += ( 'openedx.core.djangoapps.course_groups.views.cohort_discussion_topics', name='cohort_discussion_topics', ), - + url( + r'^courses/{}/verified_track_content/settings'.format( + settings.COURSE_KEY_PATTERN, + ), + 'verified_track_content.views.cohorting_settings', + name='verified_track_cohorting', + ), url( r'^courses/{}/notes$'.format( settings.COURSE_ID_PATTERN,