diff --git a/lms/djangoapps/instructor/tests/test_certificates.py b/lms/djangoapps/instructor/tests/test_certificates.py index 33cd3dc290..12ba936483 100644 --- a/lms/djangoapps/instructor/tests/test_certificates.py +++ b/lms/djangoapps/instructor/tests/test_certificates.py @@ -862,7 +862,7 @@ class TestCertificatesInstructorApiBulkAllowlist(SharedModuleStoreTestCase): assert len(data['general_errors']) == 0 assert len(data['row_errors']['data_format_error']) == 0 assert len(data['row_errors']['user_not_exist']) == 0 - assert len(data['row_errors']['user_already_white_listed']) == 0 + assert len(data['row_errors']['user_already_allowlisted']) == 0 assert len(data['row_errors']['user_not_enrolled']) == 0 assert len(data['success']) == 2 @@ -937,7 +937,7 @@ class TestCertificatesInstructorApiBulkAllowlist(SharedModuleStoreTestCase): csv_content = b"test_student1@example.com,dummy_notes" data = self.upload_file(csv_content=csv_content) - assert len(data['row_errors']['user_already_white_listed']) == 1 + assert len(data['row_errors']['user_already_allowlisted']) == 1 assert len(data['general_errors']) == 0 assert len(data['success']) == 0 diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index ba7f6df94d..ef7ac59b42 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -3152,26 +3152,32 @@ def generate_certificate_exceptions(request, course_id, generate_for=None): @require_POST def generate_bulk_certificate_exceptions(request, course_id): """ - Add Students to certificate allowlist from the uploaded csv file. - :return response in dict format. - { - general_errors: [errors related to csv file e.g. csv uploading, csv attachment, content reading etc. ], - row_errors: { - data_format_error: [users/data in csv file that are not well formatted], - user_not_exist: [csv with none exiting users in LMS system], - user_already_white_listed: [users that are already allowlisted], - user_not_enrolled: [rows with not enrolled users in the given course], - user_on_certificate_invalidation_list: [users that are currently have an active blocklist entry] - }, - success: [list of successfully added users to the certificate allowlist model] - } + Adds students to the certificate allowlist using data from the uploaded CSV file. + + Arguments: + request (WSGIRequest): Django HTTP request object. + course_id (string): Course-Run key + Returns: + dict: + { + general_errors: [errors related to csv file e.g. csv uploading, csv attachment, content reading, etc. ], + row_errors: { + data_format_error: [users/data in csv file that are not well formatted], + user_not_exist: [users that cannot be found in the LMS], + user_already_allowlisted: [users that already appear on the allowlist of this course-run], + user_not_enrolled: [users that are not currently enrolled in this course-run], + user_on_certificate_invalidation_list: [users that have an active certificate invalidation in this + course-run] + }, + success: [list of users sucessfully added to the certificate allowlist] + } """ user_index = 0 notes_index = 1 row_errors_key = [ 'data_format_error', 'user_not_exist', - 'user_already_white_listed', + 'user_already_allowlisted', 'user_not_enrolled', 'user_on_certificate_invalidation_list' ] @@ -3216,14 +3222,14 @@ def generate_bulk_certificate_exceptions(request, course_id): build_row_errors('user_not_exist', user, row_num) log.info(f'Student {user} does not exist') else: - # make sure learner isn't on the blocklist + # make sure learner doesn't have an active certificate invalidation if certs_api.is_certificate_invalidated(user, course_key): build_row_errors('user_on_certificate_invalidation_list', user, row_num) log.warning(f'Student {user.id} is blocked from receiving a Certificate in Course {course_key}') - # make sure user isn't already on the exception list + # make sure learner isn't already on the allowlist elif certs_api.is_on_allowlist(user, course_key): - build_row_errors('user_already_white_listed', user, row_num) - log.warning(f'Student {user.id} already on exception list in Course {course_key}.') + build_row_errors('user_already_allowlisted', user, row_num) + log.warning(f'Student {user.id} already appears on the allowlist in Course {course_key}.') # make sure user is enrolled in course elif not is_user_enrolled_in_course(user, course_key): build_row_errors('user_not_enrolled', user, row_num) diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index 770c75b495..99ecd484a8 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -238,7 +238,7 @@ def instructor_dashboard_2(request, course_id): # lint-amnesty, pylint: disable 'sections': sections, 'disable_buttons': disable_buttons, 'analytics_dashboard_message': analytics_dashboard_message, - 'certificate_white_list': certificate_allowlist, + 'certificate_allowlist': certificate_allowlist, 'certificate_invalidations': certificate_invalidations, 'generate_certificate_exceptions_url': generate_certificate_exceptions_url, 'generate_bulk_certificate_exceptions_url': generate_bulk_certificate_exceptions_url, diff --git a/lms/static/js/certificates/collections/certificate_whitelist.js b/lms/static/js/certificates/collections/certificate_allowlist.js similarity index 89% rename from lms/static/js/certificates/collections/certificate_whitelist.js rename to lms/static/js/certificates/collections/certificate_allowlist.js index 22e73f688a..ebc1a235ec 100644 --- a/lms/static/js/certificates/collections/certificate_whitelist.js +++ b/lms/static/js/certificates/collections/certificate_allowlist.js @@ -1,4 +1,4 @@ -// Backbone.js Application Collection: CertificateWhiteList +// Backbone.js Application Collection: CertificateAllowlist /* global define, RequireJS */ (function(define) { @@ -10,7 +10,7 @@ ], function(Backbone, gettext, CertificateExceptionModel) { - var CertificateWhiteList = Backbone.Collection.extend({ + var CertificateAllowlist = Backbone.Collection.extend({ model: CertificateExceptionModel, initialize: function(attrs, options) { @@ -42,7 +42,7 @@ var url = this.generate_certificates_url + appended_url; Backbone.sync( 'create', - new CertificateWhiteList(filtered, {url: url, generate_certificates_url: url}), + new CertificateAllowlist(filtered, {url: url, generate_certificates_url: url}), options ); }, @@ -56,7 +56,7 @@ } }); - return CertificateWhiteList; + return CertificateAllowlist; } ); }).call(this, define || RequireJS.define); diff --git a/lms/static/js/certificates/factories/certificate_allowlist_factory.js b/lms/static/js/certificates/factories/certificate_allowlist_factory.js new file mode 100644 index 0000000000..6b8eafe240 --- /dev/null +++ b/lms/static/js/certificates/factories/certificate_allowlist_factory.js @@ -0,0 +1,43 @@ +// Backbone.js Page Object Factory: Certificates +/* global define, RequireJS */ + +(function(define) { + 'use strict'; + define([ + 'jquery', + 'js/certificates/views/certificate_allowlist', + 'js/certificates/models/certificate_exception', + 'js/certificates/views/certificate_allowlist_editor', + 'js/certificates/collections/certificate_allowlist', + 'js/certificates/views/certificate_bulk_allowlist' + ], + function($, CertificateAllowlistView, CertificateExceptionModel, CertificateAllowlistEditorView, + CertificateAllowlistCollection, CertificateBulkAllowlist) { + return function(certificate_allowlist_json, generate_certificate_exceptions_url, + certificate_exception_view_url, generate_bulk_certificate_exceptions_url, + active_certificate) { + var certificateAllowlist = new CertificateAllowlistCollection(certificate_allowlist_json, { + parse: true, + canBeEmpty: true, + url: certificate_exception_view_url, + generate_certificates_url: generate_certificate_exceptions_url + }); + + var certificateAllowlistEditorView = new CertificateAllowlistEditorView({ + collection: certificateAllowlist + }); + certificateAllowlistEditorView.render(); + + new CertificateAllowlistView({ + collection: certificateAllowlist, + certificateAllowlistEditorView: certificateAllowlistEditorView, + active_certificate: active_certificate + }).render(); + + new CertificateBulkAllowlist({ + bulk_exception_url: generate_bulk_certificate_exceptions_url + }).render(); + }; + } + ); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/certificates/factories/certificate_whitelist_factory.js b/lms/static/js/certificates/factories/certificate_whitelist_factory.js deleted file mode 100644 index df8e581765..0000000000 --- a/lms/static/js/certificates/factories/certificate_whitelist_factory.js +++ /dev/null @@ -1,43 +0,0 @@ -// Backbone.js Page Object Factory: Certificates -/* global define, RequireJS */ - -(function(define) { - 'use strict'; - define([ - 'jquery', - 'js/certificates/views/certificate_whitelist', - 'js/certificates/models/certificate_exception', - 'js/certificates/views/certificate_whitelist_editor', - 'js/certificates/collections/certificate_whitelist', - 'js/certificates/views/certificate_bulk_whitelist' - ], - function($, CertificateWhiteListListView, CertificateExceptionModel, CertificateWhiteListEditorView, - CertificateWhiteListCollection, CertificateBulkWhiteList) { - return function(certificate_white_list_json, generate_certificate_exceptions_url, - certificate_exception_view_url, generate_bulk_certificate_exceptions_url, - active_certificate) { - var certificateWhiteList = new CertificateWhiteListCollection(certificate_white_list_json, { - parse: true, - canBeEmpty: true, - url: certificate_exception_view_url, - generate_certificates_url: generate_certificate_exceptions_url - }); - - var certificateWhiteListEditorView = new CertificateWhiteListEditorView({ - collection: certificateWhiteList - }); - certificateWhiteListEditorView.render(); - - new CertificateWhiteListListView({ - collection: certificateWhiteList, - certificateWhiteListEditorView: certificateWhiteListEditorView, - active_certificate: active_certificate - }).render(); - - new CertificateBulkWhiteList({ - bulk_exception_url: generate_bulk_certificate_exceptions_url - }).render(); - }; - } - ); -}).call(this, define || RequireJS.define); diff --git a/lms/static/js/certificates/models/certificate_exception.js b/lms/static/js/certificates/models/certificate_exception.js index 4f1b8dbcd9..2135f1954d 100644 --- a/lms/static/js/certificates/models/certificate_exception.js +++ b/lms/static/js/certificates/models/certificate_exception.js @@ -1,4 +1,4 @@ -// Backbone.js Application Model: CertificateWhitelist +// Backbone.js Application Model: CertificateAllowlist /* global define, RequireJS */ (function(define) { diff --git a/lms/static/js/certificates/views/certificate_whitelist.js b/lms/static/js/certificates/views/certificate_allowlist.js similarity index 91% rename from lms/static/js/certificates/views/certificate_whitelist.js rename to lms/static/js/certificates/views/certificate_allowlist.js index 06d5114689..bc80434833 100644 --- a/lms/static/js/certificates/views/certificate_whitelist.js +++ b/lms/static/js/certificates/views/certificate_allowlist.js @@ -1,4 +1,4 @@ -// Backbone Application View: CertificateWhitelist View +// Backbone Application View: CertificateAllowlist View /* global define, RequireJS */ (function(define) { @@ -14,8 +14,8 @@ function($, _, gettext, Backbone, HtmlUtils) { return Backbone.View.extend({ - el: '#white-listed-students', - message_div: 'div.white-listed-students > div.message', + el: '#allowlisted-students', + message_div: 'div.allowlisted-students > div.message', generate_exception_certificates_radio: 'input:radio[name=generate-exception-certificates-radio]:checked', @@ -25,14 +25,14 @@ }, initialize: function(options) { - this.certificateWhiteListEditorView = options.certificateWhiteListEditorView; + this.certificateAllowlistEditorView = options.certificateAllowlistEditorView; this.active_certificate = options.active_certificate; // Re-render the view when an item is added to the collection this.listenTo(this.collection, 'change add remove', this.render); }, render: function() { - var template = this.loadTemplate('certificate-white-list'); + var template = this.loadTemplate('certificate-allowlist'); this.$el.html(HtmlUtils.HTML(template({certificates: this.collection.models})).toString()); if (!this.active_certificate || this.collection.isEmpty()) { this.$('#generate-exception-certificates').attr('disabled', 'disabled'); @@ -56,7 +56,7 @@ { success: function() { self.escapeAndShowMessage( - gettext('Student Removed from certificate white list successfully.') + gettext('Student Removed from certificate allowlist successfully.') ); }, error: this.showError(this), @@ -66,7 +66,7 @@ ); } else { this.escapeAndShowMessage( - gettext('Could not find Certificate Exception in white list. Please refresh the page and try again') // eslint-disable-line max-len + gettext('Could not find Certificate Exception in the allowlist. Please refresh the page and try again') // eslint-disable-line max-len ); } }, diff --git a/lms/static/js/certificates/views/certificate_whitelist_editor.js b/lms/static/js/certificates/views/certificate_allowlist_editor.js similarity index 97% rename from lms/static/js/certificates/views/certificate_whitelist_editor.js rename to lms/static/js/certificates/views/certificate_allowlist_editor.js index fcd226f320..e46dfaf3a0 100644 --- a/lms/static/js/certificates/views/certificate_whitelist_editor.js +++ b/lms/static/js/certificates/views/certificate_allowlist_editor.js @@ -1,4 +1,4 @@ -// Backbone Application View: CertificateWhiteList Editor View +// Backbone Application View: CertificateAllowlist Editor View /* global define, RequireJS */ (function(define) { @@ -13,7 +13,7 @@ ], function($, _, gettext, Backbone, CertificateExceptionModel, HtmlUtils) { return Backbone.View.extend({ - el: '#certificate-white-list-editor', + el: '#certificate-allowlist-editor', message_div: '.message', events: { @@ -21,7 +21,7 @@ }, render: function() { - var template = this.loadTemplate('certificate-white-list-editor'); + var template = this.loadTemplate('certificate-allowlist-editor'); this.$el.html(HtmlUtils.HTML(template()).toString()); }, diff --git a/lms/static/js/certificates/views/certificate_bulk_whitelist.js b/lms/static/js/certificates/views/certificate_bulk_allowlist.js similarity index 82% rename from lms/static/js/certificates/views/certificate_bulk_whitelist.js rename to lms/static/js/certificates/views/certificate_bulk_allowlist.js index be94068979..e1ea4b51f2 100644 --- a/lms/static/js/certificates/views/certificate_bulk_whitelist.js +++ b/lms/static/js/certificates/views/certificate_bulk_allowlist.js @@ -1,4 +1,4 @@ -// Backbone Application View: CertificateBulkWhitelist View +// Backbone Application View: CertificateBulkAllowlist View /* global define, RequireJS */ (function(define) { @@ -13,10 +13,10 @@ function($, _, gettext, Backbone) { var DOM_SELECTORS = { - bulk_exception: '.bulk-white-list-exception', + bulk_exception: '.bulk-allowlist-exception', upload_csv_button: '.upload-csv-button', browse_file: '.browse-file', - bulk_white_list_exception_form: 'form#bulk-white-list-exception-form' + bulk_allowlist_exception_form: 'form#bulk-allowlist-exception-form' }; var MESSAGE_GROUP = { @@ -24,7 +24,7 @@ general_errors: 'general-errors', data_format_error: 'data-format-error', user_not_exist: 'user-not-exist', - user_already_white_listed: 'user-already-white-listed', + user_already_allowlisted: 'user-already-allowlisted', user_not_enrolled: 'user-not-enrolled', user_on_certificate_invalidation_list: 'user-on-certificate-invalidation-list' }; @@ -43,7 +43,7 @@ }, render: function() { - var template = this.loadTemplate('certificate-bulk-white-list'); + var template = this.loadTemplate('certificate-bulk-allowlist'); this.$el.html(template()); // xss-lint: disable=javascript-jquery-html }, @@ -54,7 +54,7 @@ }, uploadCSV: function() { - var form = this.$el.find(DOM_SELECTORS.bulk_white_list_exception_form); + var form = this.$el.find(DOM_SELECTORS.bulk_allowlist_exception_form); var self = this; form.unbind('submit').submit(function(e) { var data = new FormData(e.currentTarget); @@ -103,46 +103,46 @@ switch (group) { case MESSAGE_GROUP.successfully_added: text = qty > 1 ? - gettext(qty + ' learners are successfully added to exception list') : - gettext(qty + ' learner is successfully added to the exception list'); + gettext(qty + ' learners were successfully added to exception list') : + gettext(qty + ' learner was successfully added to the exception list'); break; case MESSAGE_GROUP.data_format_error: text = qty > 1 ? - gettext(qty + ' records are not in correct format and not added to' + + gettext(qty + ' records are not in the correct format and have not been added to' + ' the exception list') : - gettext(qty + ' record is not in correct format and not added to the exception' + - ' list'); + gettext(qty + ' record is not in the correct format and has not been added to the' + + ' exception list'); break; case MESSAGE_GROUP.user_not_exist: text = qty > 1 ? - gettext(qty + ' learners do not exist in LMS and not added to the' + - ' exception list') : - gettext(qty + ' learner does not exist in LMS and not added to the exception' + - ' list'); + gettext(qty + ' learner accounts cannot be found and have not been added to the ' + + 'exception list') : + gettext(qty + ' learner account cannot be found and has not been added to the' + + ' exception list'); break; - case MESSAGE_GROUP.user_already_white_listed: + case MESSAGE_GROUP.user_already_allowlisted: text = qty > 1 ? - gettext(qty + ' learners are already white listed and not added to' + - ' the exception list') : - gettext(qty + ' learner is already white listed and not added to the exception' + - ' list'); + gettext(qty + ' learners already appear on the exception list in this course') : + gettext(qty + ' learner already appears on the exception list in this course'); break; case MESSAGE_GROUP.user_not_enrolled: text = qty > 1 ? - gettext(qty + ' learners are not enrolled in course and not added to' + - ' the exception list') : - gettext(qty + ' learner is not enrolled in course and not added to the exception' + - ' list'); + gettext(qty + ' learners are not enrolled in this course and have not added to the' + + ' exception list') : + gettext(qty + ' learner is not enrolled in this course and has not been added to the' + + ' exception list'); break; case MESSAGE_GROUP.user_on_certificate_invalidation_list: text = qty > 1 ? - gettext(qty + ' learners already appear on the certificate invalidation list') : - gettext(qty + ' learner already appears on the certificate invalidation list'); + gettext(qty + ' learners have an active certificate invalidation in this course and' + + ' have not been added to the exception list') : + gettext(qty + ' learner has an active certificate invalidation in this course and has' + + ' not been added to the exception list'); break; default: @@ -195,15 +195,15 @@ user_not_exist ); } - if (row_errors.user_already_white_listed.length) { - var user_already_white_listed = row_errors.user_already_white_listed; + if (row_errors.user_already_allowlisted.length) { + var user_already_allowlisted = row_errors.user_already_allowlisted; generateDiv( - MESSAGE_GROUP.user_already_white_listed, + MESSAGE_GROUP.user_already_allowlisted, getDisplayText( - user_already_white_listed.length, - MESSAGE_GROUP.user_already_white_listed + user_already_allowlisted.length, + MESSAGE_GROUP.user_already_allowlisted ), - user_already_white_listed + user_already_allowlisted ); } if (row_errors.user_not_enrolled.length) { diff --git a/lms/static/js/spec/instructor_dashboard/certificates_bulk_exception_spec.js b/lms/static/js/spec/instructor_dashboard/certificates_bulk_exception_spec.js index b1b8151f7e..76431f29e9 100644 --- a/lms/static/js/spec/instructor_dashboard/certificates_bulk_exception_spec.js +++ b/lms/static/js/spec/instructor_dashboard/certificates_bulk_exception_spec.js @@ -1,28 +1,28 @@ define([ 'jquery', - 'js/certificates/views/certificate_bulk_whitelist' + 'js/certificates/views/certificate_bulk_allowlist' ], - function($, CertificateBulkWhiteListView) { + function($, CertificateBulkAllowlistView) { 'use strict'; describe('certificate bulk exceptions generation', function() { var certificate_bulk_exception_url = 'test/url/'; var SELECTORS = { upload_csv_button: '.upload-csv-button', - bulk_white_list_exception_form: 'form#bulk-white-list-exception-form', + bulk_allowlist_exception_form: 'form#bulk-allowlist-exception-form', bulk_exception_results: '.bulk-exception-results' }; beforeEach(function() { setFixtures(); var fixture = readFixtures( - 'templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore' + 'templates/instructor/instructor_dashboard_2/certificate-bulk-allowlist.underscore' ); setFixtures( - "' + - "
" + "' + + "
" ); - this.view = new CertificateBulkWhiteListView({ + this.view = new CertificateBulkAllowlistView({ bulk_exception_url: certificate_bulk_exception_url }); this.view.render(); @@ -41,10 +41,10 @@ define([ }; }); submitCallback = jasmine.createSpy().and.returnValue(); - this.view.$el.find(SELECTORS.bulk_white_list_exception_form).submit(submitCallback); + this.view.$el.find(SELECTORS.bulk_allowlist_exception_form).submit(submitCallback); this.view.$el.find(SELECTORS.upload_csv_button).click(); - expect($(SELECTORS.bulk_exception_results).text()).toContain('1 learner is successfully added to the ' + - 'exception list'); + expect($(SELECTORS.bulk_exception_results).text()).toContain('1 learner was successfully added to ' + + 'the exception list'); }); it('bind the ajax call and the result will be general error', function() { @@ -60,7 +60,7 @@ define([ }; }); submitCallback = jasmine.createSpy().and.returnValue(); - this.view.$el.find(SELECTORS.bulk_white_list_exception_form).submit(submitCallback); + this.view.$el.find(SELECTORS.bulk_allowlist_exception_form).submit(submitCallback); this.view.$el.find(SELECTORS.upload_csv_button).click(); expect($(SELECTORS.bulk_exception_results).text()).toContain('File is not attached.'); }); @@ -73,7 +73,7 @@ define([ row_errors: { data_format_error: ['user 1 in row# 1'], user_not_exist: ['user 2 in row# 2'], - user_already_white_listed: ['user 3 in row# 3'], + user_already_allowlisted: ['user 3 in row# 3'], user_not_enrolled: ['user 4 in row# 4'], user_on_certificate_invalidation_list: ['user 5 in row# 5'] }, @@ -84,15 +84,18 @@ define([ }; }); submitCallback = jasmine.createSpy().and.returnValue(); - this.view.$el.find(SELECTORS.bulk_white_list_exception_form).submit(submitCallback); + this.view.$el.find(SELECTORS.bulk_allowlist_exception_form).submit(submitCallback); this.view.$el.find(SELECTORS.upload_csv_button).click(); - expect($(SELECTORS.bulk_exception_results).text()).toContain('1 record is not in correct format'); - expect($(SELECTORS.bulk_exception_results).text()).toContain('1 learner does not exist in LMS'); - expect($(SELECTORS.bulk_exception_results).text()).toContain('1 learner is already white listed'); - expect($(SELECTORS.bulk_exception_results).text()).toContain('1 learner is not enrolled in course'); - expect($(SELECTORS.bulk_exception_results).text()).toContain( - '1 learner already appears on the certificate invalidation list' - ); + expect($(SELECTORS.bulk_exception_results).text()).toContain('1 record is not in the correct format ' + + 'and has not been added to the exception list'); + expect($(SELECTORS.bulk_exception_results).text()).toContain('1 learner account cannot be found and ' + + 'has not been added to the exception list'); + expect($(SELECTORS.bulk_exception_results).text()).toContain('1 learner already appears on the ' + + 'exception list in this course'); + expect($(SELECTORS.bulk_exception_results).text()).toContain('1 learner is not enrolled in this ' + + 'course and has not been added to the exception list'); + expect($(SELECTORS.bulk_exception_results).text()).toContain('1 learner has an active certificate ' + + 'invalidation in this course and has not been added to the exception list'); }); it('bind the ajax call and the result will be plural form of row errors', function() { @@ -103,7 +106,7 @@ define([ row_errors: { data_format_error: ['user 1 in row# 1', 'user 1 in row# 1'], user_not_exist: ['user 2 in row# 2', 'user 2 in row# 2'], - user_already_white_listed: ['user 3 in row# 3', 'user 3 in row# 3'], + user_already_allowlisted: ['user 3 in row# 3', 'user 3 in row# 3'], user_not_enrolled: ['user 4 in row# 4', 'user 4 in row# 4'], user_on_certificate_invalidation_list: ['user 5 in row# 5', 'user 5 in row# 5'] }, @@ -114,15 +117,18 @@ define([ }; }); submitCallback = jasmine.createSpy().and.returnValue(); - this.view.$el.find(SELECTORS.bulk_white_list_exception_form).submit(submitCallback); + this.view.$el.find(SELECTORS.bulk_allowlist_exception_form).submit(submitCallback); this.view.$el.find(SELECTORS.upload_csv_button).click(); - expect($(SELECTORS.bulk_exception_results).text()).toContain('2 records are not in correct format'); - expect($(SELECTORS.bulk_exception_results).text()).toContain('2 learners do not exist in LMS'); - expect($(SELECTORS.bulk_exception_results).text()).toContain('2 learners are already white listed'); - expect($(SELECTORS.bulk_exception_results).text()).toContain('2 learners are not enrolled in course'); - expect($(SELECTORS.bulk_exception_results).text()).toContain( - '2 learners already appear on the certificate invalidation list' - ); + expect($(SELECTORS.bulk_exception_results).text()).toContain('2 records are not in the correct ' + + 'format and have not been added to the exception list'); + expect($(SELECTORS.bulk_exception_results).text()).toContain('2 learner accounts cannot be found and ' + + 'have not been added to the exception list'); + expect($(SELECTORS.bulk_exception_results).text()).toContain('2 learners already appear on the ' + + 'exception list in this course'); + expect($(SELECTORS.bulk_exception_results).text()).toContain('2 learners are not enrolled in this ' + + 'course and have not added to the exception list'); + expect($(SELECTORS.bulk_exception_results).text()).toContain('2 learners have an active certificate ' + + 'invalidation in this course and have not been added to the exception list'); }); it('toggle message details', function() { @@ -138,7 +144,7 @@ define([ }; }); submitCallback = jasmine.createSpy().and.returnValue(); - this.view.$el.find(SELECTORS.bulk_white_list_exception_form).submit(submitCallback); + this.view.$el.find(SELECTORS.bulk_allowlist_exception_form).submit(submitCallback); this.view.$el.find(SELECTORS.upload_csv_button).click(); expect(this.view.$el.find('div.message > .successfully-added')).toBeHidden(); this.view.$el.find('.arrow#successfully-added').trigger('click'); diff --git a/lms/static/js/spec/instructor_dashboard/certificates_exception_spec.js b/lms/static/js/spec/instructor_dashboard/certificates_exception_spec.js index df8c1a9d22..4197e0583f 100644 --- a/lms/static/js/spec/instructor_dashboard/certificates_exception_spec.js +++ b/lms/static/js/spec/instructor_dashboard/certificates_exception_spec.js @@ -4,12 +4,12 @@ define([ 'sinon', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'js/certificates/models/certificate_exception', - 'js/certificates/views/certificate_whitelist', - 'js/certificates/views/certificate_whitelist_editor', - 'js/certificates/collections/certificate_whitelist' + 'js/certificates/views/certificate_allowlist', + 'js/certificates/views/certificate_allowlist_editor', + 'js/certificates/collections/certificate_allowlist' ], - function($, sinon, AjaxHelpers, CertificateExceptionModel, CertificateWhiteListView, CertificateWhiteListEditorView, - CertificateWhiteListCollection) { + function($, sinon, AjaxHelpers, CertificateExceptionModel, CertificateAllowlistView, CertificateAllowlistEditorView, + CertificateAllowlistCollection) { 'use strict'; describe('edx.certificates.models.certificates_exception.CertificateExceptionModel', function() { @@ -52,8 +52,8 @@ define([ }); }); - describe('edx.certificates.collections.certificate_whitelist.CertificateWhiteList', function() { - var certificateWhiteList = null, + describe('edx.certificates.collections.certificate_allowlist.CertificateAllowlist', function() { + var certificateAllowlist = null, certificateExceptionUrl = 'test/url/'; var certificatesExceptionsJson = [ { @@ -77,7 +77,7 @@ define([ ]; beforeEach(function() { - certificateWhiteList = new CertificateWhiteListCollection(certificatesExceptionsJson, { + certificateAllowlist = new CertificateAllowlistCollection(certificatesExceptionsJson, { parse: true, canBeEmpty: true, url: certificateExceptionUrl, @@ -86,17 +86,17 @@ define([ }); it('has 2 models in the collection after initialization', function() { - expect(certificateWhiteList.models.length).toEqual(2); + expect(certificateAllowlist.models.length).toEqual(2); }); it("returns correct model on getModel call and 'undefined' if queried model is not present", function() { - expect(certificateWhiteList.getModel({user_name: 'test1'})).not.toBe(undefined); - expect(certificateWhiteList.getModel({user_name: 'test_invalid_user'})).toBe(undefined); + expect(certificateAllowlist.getModel({user_name: 'test1'})).not.toBe(undefined); + expect(certificateAllowlist.getModel({user_name: 'test_invalid_user'})).toBe(undefined); - expect(certificateWhiteList.getModel({user_email: 'test1@test.com'})).not.toBe(undefined); - expect(certificateWhiteList.getModel({user_email: 'test_invalid_user@test.com'})).toBe(undefined); + expect(certificateAllowlist.getModel({user_email: 'test1@test.com'})).not.toBe(undefined); + expect(certificateAllowlist.getModel({user_email: 'test_invalid_user@test.com'})).toBe(undefined); - expect(certificateWhiteList.getModel({user_name: 'test1'}).attributes).toEqual( + expect(certificateAllowlist.getModel({user_name: 'test1'}).attributes).toEqual( { id: 1, user_id: 1, @@ -109,7 +109,7 @@ define([ } ); - expect(certificateWhiteList.getModel({user_email: 'test2@test.com'}).attributes).toEqual( + expect(certificateAllowlist.getModel({user_email: 'test2@test.com'}).attributes).toEqual( { id: 2, user_id: 2, @@ -133,7 +133,7 @@ define([ postData: [] }; - certificateWhiteList.sync({success: successCallback, error: errorCallback}, addStudents); + certificateAllowlist.sync({success: successCallback, error: errorCallback}, addStudents); AjaxHelpers.expectJsonRequest(requests, 'POST', expected.url, expected.postData); }); @@ -144,8 +144,8 @@ define([ addStudents = 'new', expected; - certificateWhiteList.add({user_name: 'test3', notes: 'test3 notes', new: true}); - certificateWhiteList.sync({success: successCallback, error: errorCallback}, addStudents); + certificateAllowlist.add({user_name: 'test3', notes: 'test3 notes', new: true}); + certificateAllowlist.sync({success: successCallback, error: errorCallback}, addStudents); expected = { url: certificateExceptionUrl + addStudents, @@ -163,7 +163,7 @@ define([ }); }); - describe('edx.certificates.views.certificate_whitelist.CertificateWhiteListView', function() { + describe('edx.certificates.views.certificate_allowlist.CertificateAllowlistView', function() { var view = null, certificateExceptionUrl = 'test/url/'; @@ -191,11 +191,11 @@ define([ beforeEach(function() { var fixture; setFixtures(); - fixture = readFixtures('templates/instructor/instructor_dashboard_2/certificate-white-list.underscore'); - setFixtures("' + - "
"); + fixture = readFixtures('templates/instructor/instructor_dashboard_2/certificate-allowlist.underscore'); + setFixtures("' + + "
"); - this.certificate_white_list = new CertificateWhiteListCollection(certificatesExceptionsJson, { + this.certificate_allowlist = new CertificateAllowlistCollection(certificatesExceptionsJson, { parse: true, canBeEmpty: true, url: certificateExceptionUrl, @@ -203,8 +203,8 @@ define([ }); - view = new CertificateWhiteListView({ - collection: this.certificate_white_list, + view = new CertificateAllowlistView({ + collection: this.certificate_allowlist, active_certificate: true }); view.render(); @@ -220,8 +220,8 @@ define([ expect(view.$el.find('#generate-exception-certificates').first()).not.toHaveAttr('disabled'); // Render the view with active_certificate set to false. - view = new CertificateWhiteListView({ - collection: this.certificate_white_list, + view = new CertificateAllowlistView({ + collection: this.certificate_allowlist, active_certificate: false }); view.render(); @@ -288,7 +288,7 @@ define([ }); }); - describe('edx.certificates.views.certificate_whitelist_editor.CertificateWhiteListEditorView', function() { + describe('edx.certificates.views.certificate_allowlist_editor.CertificateAllowlistEditorView', function() { var view = null, listView = null, certificateExceptionUrl = 'test/url/'; @@ -317,40 +317,40 @@ define([ ]; beforeEach(function() { - var fixture, fixture2, certificateWhiteList; + var fixture, fixture2, certificateAllowlist; setFixtures(); fixture = readFixtures( - 'templates/instructor/instructor_dashboard_2/certificate-white-list-editor.underscore' + 'templates/instructor/instructor_dashboard_2/certificate-allowlist-editor.underscore' ); fixture2 = readFixtures( - 'templates/instructor/instructor_dashboard_2/certificate-white-list.underscore' + 'templates/instructor/instructor_dashboard_2/certificate-allowlist.underscore' ); setFixtures( - "' + - "' + - "
" + - "
" + "' + + "' + + "
" + + "
" ); - certificateWhiteList = new CertificateWhiteListCollection(certificatesExceptionsJson, { + certificateAllowlist = new CertificateAllowlistCollection(certificatesExceptionsJson, { parse: true, canBeEmpty: true, url: certificateExceptionUrl, generate_certificates_url: certificateExceptionUrl }); - view = new CertificateWhiteListEditorView({ - collection: certificateWhiteList, + view = new CertificateAllowlistEditorView({ + collection: certificateAllowlist, url: certificateExceptionUrl }); view.render(); - listView = new CertificateWhiteListView({ - collection: certificateWhiteList, - certificateWhiteListEditorView: view + listView = new CertificateAllowlistView({ + collection: certificateAllowlist, + certificateAllowlistEditorView: view }); listView.render(); }); @@ -414,7 +414,7 @@ define([ it('verifies certificate exception can be deleted by clicking "delete" ', function() { var username = 'test1', - certificateExceptionSelector = "div.white-listed-students table tr:contains('" + username + "')", + certificateExceptionSelector = "div.allowlisted-students table tr:contains('" + username + "')", deleteBtnSelector = certificateExceptionSelector + ' td .delete-exception', requests = AjaxHelpers.requests(this); diff --git a/lms/static/sass/course/instructor/_instructor_2.scss b/lms/static/sass/course/instructor/_instructor_2.scss index 95a6d55d3c..2872a71ad4 100644 --- a/lms/static/sass/course/instructor/_instructor_2.scss +++ b/lms/static/sass/course/instructor/_instructor_2.scss @@ -2920,8 +2920,7 @@ input[name="subject"] { width: 400px; } - - #certificate-white-list-editor { + #certificate-allowlist-editor { padding-top: 5px; .certificate-exception-inputs { @@ -2935,7 +2934,7 @@ input[name="subject"] { } } - .white-listed-students, + .allowlisted-students, .invalidation-history { margin-top: 10px; padding-top: 5px; @@ -3022,11 +3021,11 @@ input[name="subject"] { } } - .bulk-white-list-exception { + .bulk-allowlist-exception { margin-top: 10px; padding-top: 5px; - .white-list-csv { + .allowlist-csv { .bulk-exception-results { margin-top: 10px; background-color: $gray-l4; diff --git a/lms/templates/instructor/instructor_dashboard_2/certificate-white-list-editor.underscore b/lms/templates/instructor/instructor_dashboard_2/certificate-allowlist-editor.underscore similarity index 100% rename from lms/templates/instructor/instructor_dashboard_2/certificate-white-list-editor.underscore rename to lms/templates/instructor/instructor_dashboard_2/certificate-allowlist-editor.underscore diff --git a/lms/templates/instructor/instructor_dashboard_2/certificate-white-list.underscore b/lms/templates/instructor/instructor_dashboard_2/certificate-allowlist.underscore similarity index 100% rename from lms/templates/instructor/instructor_dashboard_2/certificate-white-list.underscore rename to lms/templates/instructor/instructor_dashboard_2/certificate-allowlist.underscore diff --git a/lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore b/lms/templates/instructor/instructor_dashboard_2/certificate-bulk-allowlist.underscore similarity index 91% rename from lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore rename to lms/templates/instructor/instructor_dashboard_2/certificate-bulk-allowlist.underscore index f16557a2a3..f640e22c14 100644 --- a/lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore +++ b/lms/templates/instructor/instructor_dashboard_2/certificate-bulk-allowlist.underscore @@ -1,9 +1,9 @@

<%- gettext("Bulk Exceptions") %>

-
+

<%- gettext("Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.") %>

-
+
diff --git a/lms/templates/instructor/instructor_dashboard_2/certificates.html b/lms/templates/instructor/instructor_dashboard_2/certificates.html index ce9e955289..7d23e61d37 100644 --- a/lms/templates/instructor/instructor_dashboard_2/certificates.html +++ b/lms/templates/instructor/instructor_dashboard_2/certificates.html @@ -6,8 +6,8 @@ from django.utils.translation import ugettext as _ from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_string %> -<%static:require_module_async module_name="js/certificates/factories/certificate_whitelist_factory" class_name="CertificateWhitelistFactory"> - CertificateWhitelistFactory(${certificate_white_list | n, dump_js_escaped_json}, '${generate_certificate_exceptions_url | n, js_escaped_string}', '${certificate_exception_view_url | n, js_escaped_string}', '${generate_bulk_certificate_exceptions_url | n, js_escaped_string}', ${bool(section_data['active_certificate']) | n, dump_js_escaped_json}); +<%static:require_module_async module_name="js/certificates/factories/certificate_allowlist_factory" class_name="CertificateAllowlistFactory"> + CertificateAllowlistFactory(${certificate_allowlist | n, dump_js_escaped_json}, '${generate_certificate_exceptions_url | n, js_escaped_string}', '${certificate_exception_view_url | n, js_escaped_string}', '${generate_bulk_certificate_exceptions_url | n, js_escaped_string}', ${bool(section_data['active_certificate']) | n, dump_js_escaped_json}); <%static:require_module_async module_name="js/certificates/factories/certificate_invalidation_factory" class_name="CertificateInvalidationFactory"> @@ -186,9 +186,9 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_str "Exception Certificates below.")}

-
-
-
+
+
+
${_('Loading')}
diff --git a/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html b/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html index 1e51061786..b795f0eae6 100644 --- a/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html +++ b/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html @@ -80,7 +80,7 @@ from openedx.core.djangolib.markup import HTML ## Include Underscore templates <%block name="header_extras"> -% for template_name in ["cohorts", "discussions", "enrollment-code-lookup-links", "cohort-editor", "cohort-group-header", "cohort-selector", "cohort-form", "notification", "cohort-state", "divided-discussions-inline", "divided-discussions-course-wide", "cohort-discussions-category", "cohort-discussions-subcategory", "certificate-white-list", "certificate-white-list-editor", "certificate-bulk-white-list", "certificate-invalidation", "membership-list-widget"]: +% for template_name in ["cohorts", "discussions", "enrollment-code-lookup-links", "cohort-editor", "cohort-group-header", "cohort-selector", "cohort-form", "notification", "cohort-state", "divided-discussions-inline", "divided-discussions-course-wide", "cohort-discussions-category", "cohort-discussions-subcategory", "certificate-allowlist", "certificate-allowlist-editor", "certificate-bulk-allowlist", "certificate-invalidation", "membership-list-widget"]: