Merge pull request #27990 from edx/jhynes/microba-1179_allowlist

refactor: Rename "whitelist" references to "allowlist" where possible in Instructor Dashboard/Certificates apps
This commit is contained in:
Justin Hynes
2021-06-22 11:20:42 -04:00
committed by GitHub
18 changed files with 207 additions and 196 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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,

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -1,4 +1,4 @@
// Backbone.js Application Model: CertificateWhitelist
// Backbone.js Application Model: CertificateAllowlist
/* global define, RequireJS */
(function(define) {

View File

@@ -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
);
}
},

View File

@@ -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());
},

View File

@@ -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) {

View File

@@ -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(
"<script type='text/template' id='certificate-bulk-white-list-tpl'>" + fixture + '</script>' +
"<div class='bulk-white-list-exception'></div>"
"<script type='text/template' id='certificate-bulk-allowlist-tpl'>" + fixture + '</script>' +
"<div class='bulk-allowlist-exception'></div>"
);
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');

View File

@@ -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("<script type='text/template' id='certificate-white-list-tpl'>" + fixture + '</script>' +
"<div class='white-listed-students' id='white-listed-students'></div>");
fixture = readFixtures('templates/instructor/instructor_dashboard_2/certificate-allowlist.underscore');
setFixtures("<script type='text/template' id='certificate-allowlist-tpl'>" + fixture + '</script>' +
"<div class='allowlisted-students' id='allowlisted-students'></div>");
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(
"<script type='text/template' id='certificate-white-list-editor-tpl'>" + fixture + '</script>' +
"<script type='text/template' id='certificate-white-list-tpl'>" + fixture2 + '</script>' +
"<div id='certificate-white-list-editor'></div>" +
"<div class='white-listed-students' id='white-listed-students'></div>"
"<script type='text/template' id='certificate-allowlist-editor-tpl'>" + fixture + '</script>' +
"<script type='text/template' id='certificate-allowlist-tpl'>" + fixture2 + '</script>' +
"<div id='certificate-allowlist-editor'></div>" +
"<div class='allowlisted-students' id='allowlisted-students'></div>"
);
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);

View File

@@ -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;

View File

@@ -1,9 +1,9 @@
<h3 class="hd hd-3"><%- gettext("Bulk Exceptions") %></h3>
<div class="white-list-csv">
<div class="allowlist-csv">
<p class="under-heading">
<%- 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.") %>
</p>
<form id="bulk-white-list-exception-form" enctype="multipart/form-data">
<form id="bulk-allowlist-exception-form" enctype="multipart/form-data">
<div class="customBrowseBtn">
<label for="browseBtn-bulk-csv"><%- gettext("Upload a CSV file") %></label>
<span class="browse-file enhanced-input-file" id="bulk-exception-upload"></span>

View File

@@ -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>
<%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.")}
</p>
<div class="certificate-exception-section">
<div id="certificate-white-list-editor"></div>
<div class="bulk-white-list-exception"></div>
<div class="white-listed-students" id="white-listed-students">
<div id="certificate-allowlist-editor"></div>
<div class="bulk-allowlist-exception"></div>
<div class="allowlisted-students" id="allowlisted-students">
<div class="ui-loading">
<span class="spin"><span class="icon fa fa-refresh" aria-hidden="true"></span></span> <span class="copy">${_('Loading')}</span>
</div>

View File

@@ -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"]:
<script type="text/template" id="${template_name}-tpl">
<%static:include path="instructor/instructor_dashboard_2/${template_name}.underscore" />
</script>