Refactor shared course creation validation into create_course_utils
This commit is contained in:
@@ -1,5 +1,23 @@
|
||||
define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape"],
|
||||
function (domReady, $, _, CancelOnEscape) {
|
||||
define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/views/utils/create_course_utils"],
|
||||
function (domReady, $, _, CancelOnEscape, CreateCourseUtilsFactory) {
|
||||
var CreateCourseUtils = CreateCourseUtilsFactory({
|
||||
name: '.new-course-name',
|
||||
org: '.new-course-org',
|
||||
number: '.new-course-number',
|
||||
run: '.new-course-run',
|
||||
save: '.new-course-save',
|
||||
errorWrapper: '.wrap-error',
|
||||
errorMessage: '#course_creation_error',
|
||||
tipError: 'span.tip-error',
|
||||
error: '.error',
|
||||
allowUnicode: '.allow-unicode-course-id'
|
||||
}, {
|
||||
shown: 'is-shown',
|
||||
showing: 'is-showing',
|
||||
hiding: 'is-hiding',
|
||||
disabled: 'is-disabled',
|
||||
error: 'error'
|
||||
});
|
||||
|
||||
var dismissNotification = function (e) {
|
||||
e.preventDefault();
|
||||
@@ -14,19 +32,7 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape"],
|
||||
var saveNewCourse = function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
// One final check for empty values
|
||||
var errors = _.reduce(
|
||||
['.new-course-name', '.new-course-org', '.new-course-number', '.new-course-run'],
|
||||
function (acc, ele) {
|
||||
var $ele = $(ele);
|
||||
var error = validateRequiredField($ele.val());
|
||||
setNewCourseFieldInErr($ele.parent('li'), error);
|
||||
return error ? true : acc;
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
if (errors) {
|
||||
if (CreateCourseUtils.hasInvalidRequiredFields()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -36,29 +42,19 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape"],
|
||||
var number = $newCourseForm.find('.new-course-number').val();
|
||||
var run = $newCourseForm.find('.new-course-run').val();
|
||||
|
||||
analytics.track('Created a Course', {
|
||||
'org': org,
|
||||
'number': number,
|
||||
'display_name': display_name,
|
||||
'run': run
|
||||
});
|
||||
course_info = {
|
||||
org: org,
|
||||
number: number,
|
||||
display_name: display_name,
|
||||
run: run
|
||||
};
|
||||
|
||||
$.postJSON('/course/', {
|
||||
'org': org,
|
||||
'number': number,
|
||||
'display_name': display_name,
|
||||
'run': run
|
||||
},
|
||||
function (data) {
|
||||
if (data.url !== undefined) {
|
||||
window.location = data.url;
|
||||
} else if (data.ErrMsg !== undefined) {
|
||||
$('.wrap-error').addClass('is-shown');
|
||||
$('#course_creation_error').html('<p>' + data.ErrMsg + '</p>');
|
||||
$('.new-course-save').addClass('is-disabled');
|
||||
}
|
||||
}
|
||||
);
|
||||
analytics.track('Created a Course', course_info);
|
||||
CreateCourseUtils.createCourse(course_info, function (errorMessage) {
|
||||
$('.wrap-error').addClass('is-shown');
|
||||
$('#course_creation_error').html('<p>' + errorMessage + '</p>');
|
||||
$('.new-course-save').addClass('is-disabled');
|
||||
});
|
||||
};
|
||||
|
||||
var cancelNewCourse = function (e) {
|
||||
@@ -77,25 +73,6 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape"],
|
||||
$('.new-course-save').off('click');
|
||||
};
|
||||
|
||||
// Check that a course (org, number, run) doesn't use any special characters
|
||||
var validateCourseItemEncoding = function (item) {
|
||||
var required = validateRequiredField(item);
|
||||
if (required) {
|
||||
return required;
|
||||
}
|
||||
if ($('.allow-unicode-course-id').val() === 'True'){
|
||||
if (/\s/g.test(item)) {
|
||||
return gettext('Please do not use any spaces in this field.');
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (item !== encodeURIComponent(item)) {
|
||||
return gettext('Please do not use any spaces or special characters in this field.');
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
var addNewCourse = function (e) {
|
||||
e.preventDefault();
|
||||
$('.new-course-button').addClass('is-disabled');
|
||||
@@ -108,68 +85,7 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape"],
|
||||
$cancelButton.bind('click', cancelNewCourse);
|
||||
CancelOnEscape($cancelButton);
|
||||
|
||||
// Ensure that org/course_num/run < 65 chars.
|
||||
var validateTotalCourseItemsLength = function () {
|
||||
var totalLength = _.reduce(
|
||||
['.new-course-org', '.new-course-number', '.new-course-run'],
|
||||
function (sum, ele) {
|
||||
return sum + $(ele).val().length;
|
||||
}, 0
|
||||
);
|
||||
if (totalLength > 65) {
|
||||
$('.wrap-error').addClass('is-shown');
|
||||
$('#course_creation_error').html('<p>' + gettext('The combined length of the organization, course number, and course run fields cannot be more than 65 characters.') + '</p>');
|
||||
$('.new-course-save').addClass('is-disabled');
|
||||
}
|
||||
else {
|
||||
$('.wrap-error').removeClass('is-shown');
|
||||
}
|
||||
};
|
||||
|
||||
// Handle validation asynchronously
|
||||
_.each(
|
||||
['.new-course-org', '.new-course-number', '.new-course-run'],
|
||||
function (ele) {
|
||||
var $ele = $(ele);
|
||||
$ele.on('keyup', function (event) {
|
||||
// Don't bother showing "required field" error when
|
||||
// the user tabs into a new field; this is distracting
|
||||
// and unnecessary
|
||||
if (event.keyCode === 9) {
|
||||
return;
|
||||
}
|
||||
var error = validateCourseItemEncoding($ele.val());
|
||||
setNewCourseFieldInErr($ele.parent('li'), error);
|
||||
validateTotalCourseItemsLength();
|
||||
});
|
||||
}
|
||||
);
|
||||
var $name = $('.new-course-name');
|
||||
$name.on('keyup', function () {
|
||||
var error = validateRequiredField($name.val());
|
||||
setNewCourseFieldInErr($name.parent('li'), error);
|
||||
validateTotalCourseItemsLength();
|
||||
});
|
||||
};
|
||||
|
||||
var validateRequiredField = function (msg) {
|
||||
return msg.length === 0 ? gettext('Required field.') : '';
|
||||
};
|
||||
|
||||
var setNewCourseFieldInErr = function (el, msg) {
|
||||
if(msg) {
|
||||
el.addClass('error');
|
||||
el.children('span.tip-error').addClass('is-showing').removeClass('is-hiding').text(msg);
|
||||
$('.new-course-save').addClass('is-disabled');
|
||||
}
|
||||
else {
|
||||
el.removeClass('error');
|
||||
el.children('span.tip-error').addClass('is-hiding').removeClass('is-showing');
|
||||
// One "error" div is always present, but hidden or shown
|
||||
if($('.error').length === 1) {
|
||||
$('.new-course-save').removeClass('is-disabled');
|
||||
}
|
||||
}
|
||||
CreateCourseUtils.configureHandlers();
|
||||
};
|
||||
|
||||
var onReady = function () {
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers", "js/views/course_rerun"],
|
||||
function ($, create_sinon, view_helpers, CourseRerunUtils) {
|
||||
define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers", "js/views/course_rerun",
|
||||
"js/views/utils/create_course_utils"],
|
||||
function ($, create_sinon, view_helpers, CourseRerunUtils, CreateCourseUtilsFactory) {
|
||||
describe("Create course rerun page", function () {
|
||||
var selectors = {
|
||||
courseOrg: '.rerun-course-org',
|
||||
courseNumber: '.rerun-course-number',
|
||||
courseRun: '.rerun-course-run',
|
||||
courseName: '.rerun-course-name',
|
||||
errorField: '.tip-error',
|
||||
saveButton: '.rerun-course-save',
|
||||
cancelButton: '.rerun-course-cancel',
|
||||
errorMessage: '.wrapper-error'
|
||||
org: '.rerun-course-org',
|
||||
number: '.rerun-course-number',
|
||||
run: '.rerun-course-run',
|
||||
name: '.rerun-course-name',
|
||||
tipError: 'span.tip-error',
|
||||
save: '.rerun-course-save',
|
||||
cancel: '.rerun-course-cancel',
|
||||
errorWrapper: '.wrapper-error',
|
||||
errorMessage: '#course_rerun_error',
|
||||
error: '.error',
|
||||
allowUnicode: '.allow-unicode-course-id'
|
||||
},
|
||||
classes = {
|
||||
shown: 'is-shown',
|
||||
showing: 'is-showing',
|
||||
hiding: 'is-hidden',
|
||||
hidden: 'is-hidden',
|
||||
error: 'error',
|
||||
disabled: 'is-disabled',
|
||||
@@ -19,11 +26,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
|
||||
},
|
||||
mockCreateCourseRerunHTML = readFixtures('mock/mock-create-course-rerun.underscore');
|
||||
|
||||
var CreateCourseUtils = CreateCourseUtilsFactory(selectors, classes);
|
||||
|
||||
var fillInFields = function (org, number, run, name) {
|
||||
$(selectors.courseOrg).val(org);
|
||||
$(selectors.courseNumber).val(number);
|
||||
$(selectors.courseRun).val(run);
|
||||
$(selectors.courseName).val(name);
|
||||
$(selectors.org).val(org);
|
||||
$(selectors.number).val(number);
|
||||
$(selectors.run).val(run);
|
||||
$(selectors.name).val(name);
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
@@ -40,12 +49,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
|
||||
|
||||
describe("Field validation", function () {
|
||||
it("returns a message for an empty string", function () {
|
||||
var message = CourseRerunUtils.validateRequiredField('');
|
||||
var message = CreateCourseUtils.validateRequiredField('');
|
||||
expect(message).not.toBe('');
|
||||
});
|
||||
|
||||
it("does not return a message for a non empty string", function () {
|
||||
var message = CourseRerunUtils.validateRequiredField('edX');
|
||||
var message = CreateCourseUtils.validateRequiredField('edX');
|
||||
expect(message).toBe('');
|
||||
});
|
||||
});
|
||||
@@ -53,43 +62,43 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
|
||||
describe("Error messages", function () {
|
||||
var setErrorMessage = function(selector, message) {
|
||||
var element = $(selector).parent();
|
||||
CourseRerunUtils.setNewCourseFieldInErr(element, message);
|
||||
CreateCourseUtils.setNewCourseFieldInErr(element, message);
|
||||
return element;
|
||||
};
|
||||
|
||||
it("shows an error message", function () {
|
||||
var element = setErrorMessage(selectors.courseOrg, 'error message');
|
||||
var element = setErrorMessage(selectors.org, 'error message');
|
||||
expect(element).toHaveClass(classes.error);
|
||||
expect(element.children(selectors.errorField)).not.toHaveClass(classes.hidden);
|
||||
expect(element.children(selectors.errorField)).toContainText('error message');
|
||||
expect(element.children(selectors.tipError)).not.toHaveClass(classes.hidden);
|
||||
expect(element.children(selectors.tipError)).toContainText('error message');
|
||||
});
|
||||
|
||||
it("hides an error message", function () {
|
||||
var element = setErrorMessage(selectors.courseOrg, '');
|
||||
var element = setErrorMessage(selectors.org, '');
|
||||
expect(element).not.toHaveClass(classes.error);
|
||||
expect(element.children(selectors.errorField)).toHaveClass(classes.hidden);
|
||||
expect(element.children(selectors.tipError)).toHaveClass(classes.hidden);
|
||||
});
|
||||
|
||||
it("disables the save button", function () {
|
||||
setErrorMessage(selectors.courseOrg, 'error message');
|
||||
expect($(selectors.saveButton)).toHaveClass(classes.disabled);
|
||||
setErrorMessage(selectors.org, 'error message');
|
||||
expect($(selectors.save)).toHaveClass(classes.disabled);
|
||||
});
|
||||
|
||||
it("enables the save button when all errors are removed", function () {
|
||||
setErrorMessage(selectors.courseOrg, 'error message 1');
|
||||
setErrorMessage(selectors.courseNumber, 'error message 2');
|
||||
expect($(selectors.saveButton)).toHaveClass(classes.disabled);
|
||||
setErrorMessage(selectors.courseOrg, '');
|
||||
setErrorMessage(selectors.courseNumber, '');
|
||||
expect($(selectors.saveButton)).not.toHaveClass(classes.disabled);
|
||||
setErrorMessage(selectors.org, 'error message 1');
|
||||
setErrorMessage(selectors.number, 'error message 2');
|
||||
expect($(selectors.save)).toHaveClass(classes.disabled);
|
||||
setErrorMessage(selectors.org, '');
|
||||
setErrorMessage(selectors.number, '');
|
||||
expect($(selectors.save)).not.toHaveClass(classes.disabled);
|
||||
});
|
||||
|
||||
it("does not enable the save button when errors remain", function () {
|
||||
setErrorMessage(selectors.courseOrg, 'error message 1');
|
||||
setErrorMessage(selectors.courseNumber, 'error message 2');
|
||||
expect($(selectors.saveButton)).toHaveClass(classes.disabled);
|
||||
setErrorMessage(selectors.courseOrg, '');
|
||||
expect($(selectors.saveButton)).toHaveClass(classes.disabled);
|
||||
setErrorMessage(selectors.org, 'error message 1');
|
||||
setErrorMessage(selectors.number, 'error message 2');
|
||||
expect($(selectors.save)).toHaveClass(classes.disabled);
|
||||
setErrorMessage(selectors.org, '');
|
||||
expect($(selectors.save)).toHaveClass(classes.disabled);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -97,7 +106,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
|
||||
var requests = create_sinon.requests(this);
|
||||
window.source_course_key = 'test_course_key';
|
||||
fillInFields('DemoX', 'DM101', '2014', 'Demo course');
|
||||
$(selectors.saveButton).click();
|
||||
$(selectors.save).click();
|
||||
create_sinon.expectJsonRequest(requests, 'POST', '/course/', {
|
||||
source_course_key: 'test_course_key',
|
||||
org: 'DemoX',
|
||||
@@ -105,28 +114,28 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
|
||||
run: '2014',
|
||||
display_name: 'Demo course'
|
||||
});
|
||||
expect($(selectors.saveButton)).toHaveClass(classes.disabled);
|
||||
expect($(selectors.saveButton)).toHaveClass(classes.processing);
|
||||
expect($(selectors.cancelButton)).toHaveClass(classes.hidden);
|
||||
expect($(selectors.save)).toHaveClass(classes.disabled);
|
||||
expect($(selectors.save)).toHaveClass(classes.processing);
|
||||
expect($(selectors.cancel)).toHaveClass(classes.hidden);
|
||||
});
|
||||
|
||||
it("displays an error when saving fails", function () {
|
||||
var requests = create_sinon.requests(this);
|
||||
fillInFields('DemoX', 'DM101', '2014', 'Demo course');
|
||||
$(selectors.saveButton).click();
|
||||
$(selectors.save).click();
|
||||
create_sinon.respondWithJson(requests, {
|
||||
ErrMsg: 'error message'
|
||||
});
|
||||
expect($(selectors.errorMessage)).not.toHaveClass(classes.hidden);
|
||||
expect($(selectors.errorMessage)).toContainText('error message');
|
||||
expect($(selectors.saveButton)).not.toHaveClass(classes.processing);
|
||||
expect($(selectors.cancelButton)).not.toHaveClass(classes.hidden);
|
||||
expect($(selectors.errorWrapper)).not.toHaveClass(classes.hidden);
|
||||
expect($(selectors.errorWrapper)).toContainText('error message');
|
||||
expect($(selectors.save)).not.toHaveClass(classes.processing);
|
||||
expect($(selectors.cancel)).not.toHaveClass(classes.hidden);
|
||||
});
|
||||
|
||||
it("does not save if there are validation errors", function () {
|
||||
var requests = create_sinon.requests(this);
|
||||
fillInFields('DemoX', 'DM101', '', 'Demo course');
|
||||
$(selectors.saveButton).click();
|
||||
$(selectors.save).click();
|
||||
expect(requests.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
define(["domReady", "jquery", "underscore"],
|
||||
function (domReady, $, _) {
|
||||
define(["domReady", "jquery", "underscore", "js/views/utils/create_course_utils"],
|
||||
function (domReady, $, _, CreateCourseUtilsFactory) {
|
||||
var CreateCourseUtils = CreateCourseUtilsFactory({
|
||||
name: '.rerun-course-name',
|
||||
org: '.rerun-course-org',
|
||||
number: '.rerun-course-number',
|
||||
run: '.rerun-course-run',
|
||||
save: '.rerun-course-save',
|
||||
errorWrapper: '.wrapper-error',
|
||||
errorMessage: '#course_rerun_error',
|
||||
tipError: 'span.tip-error',
|
||||
error: '.error',
|
||||
allowUnicode: '.allow-unicode-course-id'
|
||||
}, {
|
||||
shown: 'is-shown',
|
||||
showing: 'is-showing',
|
||||
hiding: 'is-hidden',
|
||||
disabled: 'is-disabled',
|
||||
error: 'error'
|
||||
});
|
||||
|
||||
var saveRerunCourse = function (e) {
|
||||
e.preventDefault();
|
||||
// One final check for errors
|
||||
var errors = _.reduce(
|
||||
['.rerun-course-name', '.rerun-course-org', '.rerun-course-number', '.rerun-course-run'],
|
||||
function (acc, ele) {
|
||||
var $ele = $(ele);
|
||||
var error = validateRequiredField($ele.val());
|
||||
setNewCourseFieldInErr($ele.parent('li'), error);
|
||||
return error ? true : acc;
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
if (errors) {
|
||||
if (CreateCourseUtils.hasInvalidRequiredFields()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,31 +32,22 @@ define(["domReady", "jquery", "underscore"],
|
||||
var number = $newCourseForm.find('.rerun-course-number').val();
|
||||
var run = $newCourseForm.find('.rerun-course-run').val();
|
||||
|
||||
analytics.track('Reran a Course', {
|
||||
'source_course_key': source_course_key,
|
||||
'org': org,
|
||||
'number': number,
|
||||
'display_name': display_name,
|
||||
'run': run
|
||||
course_info = {
|
||||
source_course_key: source_course_key,
|
||||
org: org,
|
||||
number: number,
|
||||
display_name: display_name,
|
||||
run: run
|
||||
};
|
||||
|
||||
analytics.track('Reran a Course', course_info);
|
||||
CreateCourseUtils.createCourse(course_info, function (errorMessage) {
|
||||
$('.wrapper-error').addClass('is-shown').removeClass('is-hidden');
|
||||
$('#course_rerun_error').html('<p>' + errorMessage + '</p>');
|
||||
$('.rerun-course-save').addClass('is-disabled').removeClass('is-processing').html(gettext('Create Re-run'));
|
||||
$('.action-cancel').removeClass('is-hidden');
|
||||
});
|
||||
$.postJSON('/course/', {
|
||||
'source_course_key': source_course_key,
|
||||
'org': org,
|
||||
'number': number,
|
||||
'display_name': display_name,
|
||||
'run': run
|
||||
},
|
||||
function (data) {
|
||||
if (data.url !== undefined) {
|
||||
window.location = data.url;
|
||||
} else if (data.ErrMsg !== undefined) {
|
||||
$('.wrapper-error').addClass('is-shown').removeClass('is-hidden');
|
||||
$('#course_rerun_error').html('<p>' + data.ErrMsg + '</p>');
|
||||
$('.rerun-course-save').addClass('is-disabled').removeClass('is-processing').html(gettext('Create Re-run'));
|
||||
$('.action-cancel').removeClass('is-hidden');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Go into creating re-run state
|
||||
$('.rerun-course-save').addClass('is-disabled').addClass('is-processing').html(
|
||||
'<i class="icon icon-refresh icon-spin"></i>' + gettext('Processing Re-run Request')
|
||||
@@ -67,26 +65,6 @@ define(["domReady", "jquery", "underscore"],
|
||||
window.location.href = '/course/';
|
||||
};
|
||||
|
||||
var validateRequiredField = function (msg) {
|
||||
return msg.length === 0 ? gettext('Required field.') : '';
|
||||
};
|
||||
|
||||
var setNewCourseFieldInErr = function (el, msg) {
|
||||
if(msg) {
|
||||
el.addClass('error');
|
||||
el.children('span.tip-error').addClass('is-shown').removeClass('is-hidden').text(msg);
|
||||
$('.rerun-course-save').addClass('is-disabled');
|
||||
}
|
||||
else {
|
||||
el.removeClass('error');
|
||||
el.children('span.tip-error').addClass('is-hidden').removeClass('is-shown');
|
||||
// One "error" div is always present, but hidden or shown
|
||||
if($('.error').length === 1) {
|
||||
$('.rerun-course-save').removeClass('is-disabled');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var onReady = function () {
|
||||
var $cancelButton = $('.rerun-course-cancel');
|
||||
var $courseRun = $('.rerun-course-run');
|
||||
@@ -95,85 +73,7 @@ define(["domReady", "jquery", "underscore"],
|
||||
$cancelButton.bind('click', cancelRerunCourse);
|
||||
$('.cancel-button').bind('click', cancelRerunCourse);
|
||||
|
||||
// Check that a course (org, number, run) doesn't use any special characters
|
||||
var validateCourseItemEncoding = function (item) {
|
||||
var required = validateRequiredField(item);
|
||||
if (required) {
|
||||
return required;
|
||||
}
|
||||
if ($('.allow-unicode-course-id').val() === 'True'){
|
||||
if (/\s/g.test(item)) {
|
||||
return gettext('Please do not use any spaces in this field.');
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (item !== encodeURIComponent(item)) {
|
||||
return gettext('Please do not use any spaces or special characters in this field.');
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
// Ensure that org/course_num/run < 65 chars.
|
||||
var validateTotalCourseItemsLength = function () {
|
||||
var totalLength = _.reduce(
|
||||
['.rerun-course-org', '.rerun-course-number', '.rerun-course-run'],
|
||||
function (sum, ele) {
|
||||
return sum + $(ele).val().length;
|
||||
}, 0
|
||||
);
|
||||
if (totalLength > 65) {
|
||||
$('.wrap-error').addClass('is-shown');
|
||||
$('#course_creation_error').html('<p>' + gettext('The combined length of the organization, course number, and course run fields cannot be more than 65 characters.') + '</p>');
|
||||
$('.rerun-course-save').addClass('is-disabled');
|
||||
}
|
||||
else {
|
||||
$('.wrap-error').removeClass('is-shown');
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure that all fields are not empty
|
||||
var validateFilledFields = function () {
|
||||
return _.reduce(
|
||||
['.rerun-course-org', '.rerun-course-number', '.rerun-course-run', '.rerun-course-name'],
|
||||
function (acc, ele) {
|
||||
var $ele = $(ele);
|
||||
return $ele.val().length !== 0 ? acc : false;
|
||||
},
|
||||
true
|
||||
);
|
||||
};
|
||||
|
||||
// Handle validation asynchronously
|
||||
_.each(
|
||||
['.rerun-course-org', '.rerun-course-number', '.rerun-course-run'],
|
||||
function (ele) {
|
||||
var $ele = $(ele);
|
||||
$ele.on('keyup', function (event) {
|
||||
// Don't bother showing "required field" error when
|
||||
// the user tabs into a new field; this is distracting
|
||||
// and unnecessary
|
||||
if (event.keyCode === 9) {
|
||||
return;
|
||||
}
|
||||
var error = validateCourseItemEncoding($ele.val());
|
||||
setNewCourseFieldInErr($ele.parent(), error);
|
||||
validateTotalCourseItemsLength();
|
||||
if(!validateFilledFields()) {
|
||||
$('.rerun-course-save').addClass('is-disabled');
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
var $name = $('.rerun-course-name');
|
||||
$name.on('keyup', function () {
|
||||
var error = validateRequiredField($name.val());
|
||||
setNewCourseFieldInErr($name.parent(), error);
|
||||
validateTotalCourseItemsLength();
|
||||
if(!validateFilledFields()) {
|
||||
$('.rerun-course-save').addClass('is-disabled');
|
||||
}
|
||||
});
|
||||
CreateCourseUtils.configureHandlers();
|
||||
};
|
||||
|
||||
domReady(onReady);
|
||||
@@ -182,8 +82,6 @@ define(["domReady", "jquery", "underscore"],
|
||||
return {
|
||||
saveRerunCourse: saveRerunCourse,
|
||||
cancelRerunCourse: cancelRerunCourse,
|
||||
validateRequiredField: validateRequiredField,
|
||||
setNewCourseFieldInErr: setNewCourseFieldInErr,
|
||||
onReady: onReady
|
||||
};
|
||||
});
|
||||
|
||||
151
cms/static/js/views/utils/create_course_utils.js
Normal file
151
cms/static/js/views/utils/create_course_utils.js
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Provides utilities for validating courses during creation, for both new courses and reruns.
|
||||
*/
|
||||
define(["jquery", "underscore", "gettext"],
|
||||
function ($, _, gettext) {
|
||||
return function (selectors, classes) {
|
||||
var validateRequiredField, validateCourseItemEncoding, validateTotalCourseItemsLength, setNewCourseFieldInErr,
|
||||
hasInvalidRequiredFields, createCourse, validateFilledFields, configureHandlers;
|
||||
|
||||
validateRequiredField = function (msg) {
|
||||
return msg.length === 0 ? gettext('Required field.') : '';
|
||||
};
|
||||
|
||||
// Check that a course (org, number, run) doesn't use any special characters
|
||||
validateCourseItemEncoding = function (item) {
|
||||
var required = validateRequiredField(item);
|
||||
if (required) {
|
||||
return required;
|
||||
}
|
||||
if ($(selectors.allowUnicode).val() === 'True') {
|
||||
if (/\s/g.test(item)) {
|
||||
return gettext('Please do not use any spaces in this field.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (item !== encodeURIComponent(item)) {
|
||||
return gettext('Please do not use any spaces or special characters in this field.');
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
// Ensure that org/course_num/run < 65 chars.
|
||||
validateTotalCourseItemsLength = function () {
|
||||
var totalLength = _.reduce(
|
||||
[selectors.org, selectors.number, selectors.run],
|
||||
function (sum, ele) {
|
||||
return sum + $(ele).val().length;
|
||||
}, 0
|
||||
);
|
||||
if (totalLength > 65) {
|
||||
$(selectors.errorWrapper).addClass(classes.shown);
|
||||
$(selectors.errorMessage).html('<p>' + gettext('The combined length of the organization, course number, and course run fields cannot be more than 65 characters.') + '</p>');
|
||||
$(selectors.save).addClass(classes.disabled);
|
||||
}
|
||||
else {
|
||||
$(selectors.errorWrapper).removeClass(classes.shown);
|
||||
}
|
||||
};
|
||||
|
||||
setNewCourseFieldInErr = function (el, msg) {
|
||||
if (msg) {
|
||||
el.addClass(classes.error);
|
||||
el.children(selectors.tipError).addClass(classes.showing).removeClass(classes.hiding).text(msg);
|
||||
$(selectors.save).addClass(classes.disabled);
|
||||
}
|
||||
else {
|
||||
el.removeClass(classes.error);
|
||||
el.children(selectors.tipError).addClass(classes.hiding).removeClass(classes.showing);
|
||||
// One "error" div is always present, but hidden or shown
|
||||
if ($(selectors.error).length === 1) {
|
||||
$(selectors.save).removeClass(classes.disabled);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// One final check for empty values
|
||||
hasInvalidRequiredFields = function () {
|
||||
return _.reduce(
|
||||
[selectors.name, selectors.org, selectors.number, selectors.run],
|
||||
function (acc, ele) {
|
||||
var $ele = $(ele);
|
||||
var error = validateRequiredField($ele.val());
|
||||
setNewCourseFieldInErr($ele.parent(), error);
|
||||
return error ? true : acc;
|
||||
},
|
||||
false
|
||||
);
|
||||
};
|
||||
|
||||
createCourse = function (courseInfo, errorHandler) {
|
||||
$.postJSON(
|
||||
'/course/',
|
||||
courseInfo,
|
||||
function (data) {
|
||||
if (data.url !== undefined) {
|
||||
window.location = data.url;
|
||||
} else if (data.ErrMsg !== undefined) {
|
||||
errorHandler(data.ErrMsg);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
// Ensure that all fields are not empty
|
||||
validateFilledFields = function () {
|
||||
return _.reduce(
|
||||
[selectors.org, selectors.number, selectors.run, selectors.name],
|
||||
function (acc, ele) {
|
||||
var $ele = $(ele);
|
||||
return $ele.val().length !== 0 ? acc : false;
|
||||
},
|
||||
true
|
||||
);
|
||||
};
|
||||
|
||||
// Handle validation asynchronously
|
||||
configureHandlers = function () {
|
||||
_.each(
|
||||
[selectors.org, selectors.number, selectors.run],
|
||||
function (ele) {
|
||||
var $ele = $(ele);
|
||||
$ele.on('keyup', function (event) {
|
||||
// Don't bother showing "required field" error when
|
||||
// the user tabs into a new field; this is distracting
|
||||
// and unnecessary
|
||||
if (event.keyCode === 9) {
|
||||
return;
|
||||
}
|
||||
var error = validateCourseItemEncoding($ele.val());
|
||||
setNewCourseFieldInErr($ele.parent(), error);
|
||||
validateTotalCourseItemsLength();
|
||||
if (!validateFilledFields()) {
|
||||
$(selectors.save).addClass(classes.disabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
var $name = $(selectors.name);
|
||||
$name.on('keyup', function () {
|
||||
var error = validateRequiredField($name.val());
|
||||
setNewCourseFieldInErr($name.parent(), error);
|
||||
validateTotalCourseItemsLength();
|
||||
if (!validateFilledFields()) {
|
||||
$(selectors.save).addClass(classes.disabled);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
validateRequiredField: validateRequiredField,
|
||||
validateCourseItemEncoding: validateCourseItemEncoding,
|
||||
validateTotalCourseItemsLength: validateTotalCourseItemsLength,
|
||||
setNewCourseFieldInErr: setNewCourseFieldInErr,
|
||||
hasInvalidRequiredFields: hasInvalidRequiredFields,
|
||||
createCourse: createCourse,
|
||||
validateFilledFields: validateFilledFields,
|
||||
configureHandlers: configureHandlers
|
||||
};
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user