Commit d43e915d by Brian Jacobel

Run eslint autofixer on /cms

parent c7042c48
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
var getModulesList = function(modules) { var getModulesList = function(modules) {
var result = [getModule(commonLibrariesPath)]; var result = [getModule(commonLibrariesPath)];
return result.concat(modules.map(function (moduleName) { return result.concat(modules.map(function(moduleName) {
return getModule(moduleName, true); return getModule(moduleName, true);
})); }));
}; };
...@@ -171,4 +171,5 @@ ...@@ -171,4 +171,5 @@
*/ */
logLevel: 1 logLevel: 1
}; };
}()) }()) // eslint-disable-line semi
// A semicolon on the line above will break the requirejs optimizer
;(function(require, define) { (function(require, define) {
'use strict'; 'use strict';
if (window) { if (window) {
...@@ -210,12 +210,12 @@ ...@@ -210,12 +210,12 @@
window.MathJax.Hub.Config({ window.MathJax.Hub.Config({
tex2jax: { tex2jax: {
inlineMath: [ inlineMath: [
['\\(','\\)'], ['\\(', '\\)'],
['[mathjaxinline]','[/mathjaxinline]'] ['[mathjaxinline]', '[/mathjaxinline]']
], ],
displayMath: [ displayMath: [
['\\[','\\]'], ['\\[', '\\]'],
['[mathjax]','[/mathjax]'] ['[mathjax]', '[/mathjax]']
] ]
} }
}); });
......
...@@ -2,81 +2,81 @@ ...@@ -2,81 +2,81 @@
(function(sandbox) { (function(sandbox) {
'use strict'; 'use strict';
require(["jquery", "backbone", "cms/js/main", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers", "jquery.cookie"], require(['jquery', 'backbone', 'cms/js/main', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'jquery.cookie'],
function($, Backbone, main, AjaxHelpers) { function($, Backbone, main, AjaxHelpers) {
describe("CMS", function() { describe('CMS', function() {
it("should initialize URL", function() { it('should initialize URL', function() {
expect(window.CMS.URL).toBeDefined(); expect(window.CMS.URL).toBeDefined();
}); });
});
describe("main helper", function() {
beforeEach(function() {
this.previousAjaxSettings = $.extend(true, {}, $.ajaxSettings);
spyOn($, "cookie").and.callFake(function(param) {
if (param === "csrftoken") {
return "stubCSRFToken";
}
}); });
return main(); describe('main helper', function() {
}); beforeEach(function() {
afterEach(function() { this.previousAjaxSettings = $.extend(true, {}, $.ajaxSettings);
$.ajaxSettings = this.previousAjaxSettings; spyOn($, 'cookie').and.callFake(function(param) {
return $.ajaxSettings; if (param === 'csrftoken') {
}); return 'stubCSRFToken';
it("turn on Backbone emulateHTTP", function() { }
expect(Backbone.emulateHTTP).toBeTruthy(); });
}); return main();
it("setup AJAX CSRF token", function() { });
expect($.ajaxSettings.headers["X-CSRFToken"]).toEqual("stubCSRFToken"); afterEach(function() {
}); $.ajaxSettings = this.previousAjaxSettings;
}); return $.ajaxSettings;
describe("AJAX Errors", function() { });
var server; it('turn on Backbone emulateHTTP', function() {
server = null; expect(Backbone.emulateHTTP).toBeTruthy();
beforeEach(function() { });
appendSetFixtures(sandbox({ it('setup AJAX CSRF token', function() {
id: "page-notification" expect($.ajaxSettings.headers['X-CSRFToken']).toEqual('stubCSRFToken');
})); });
}); });
afterEach(function() { describe('AJAX Errors', function() {
return server && server.restore(); var server;
}); server = null;
it("successful AJAX request does not pop an error notification", function() { beforeEach(function() {
server = AjaxHelpers.server([ appendSetFixtures(sandbox({
200, { id: 'page-notification'
"Content-Type": "application/json" }));
}, "{}" });
]); afterEach(function() {
expect($("#page-notification")).toBeEmpty(); return server && server.restore();
$.ajax("/test"); });
expect($("#page-notification")).toBeEmpty(); it('successful AJAX request does not pop an error notification', function() {
server.respond(); server = AjaxHelpers.server([
expect($("#page-notification")).toBeEmpty(); 200, {
}); 'Content-Type': 'application/json'
it("AJAX request with error should pop an error notification", function() { }, '{}'
server = AjaxHelpers.server([ ]);
500, { expect($('#page-notification')).toBeEmpty();
"Content-Type": "application/json" $.ajax('/test');
}, "{}" expect($('#page-notification')).toBeEmpty();
]); server.respond();
$.ajax("/test"); expect($('#page-notification')).toBeEmpty();
server.respond(); });
expect($("#page-notification")).not.toBeEmpty(); it('AJAX request with error should pop an error notification', function() {
expect($("#page-notification")).toContainElement('div.wrapper-notification-error'); server = AjaxHelpers.server([
}); 500, {
it("can override AJAX request with error so it does not pop an error notification", function() { 'Content-Type': 'application/json'
server = AjaxHelpers.server([ }, '{}'
500, { ]);
"Content-Type": "application/json" $.ajax('/test');
}, "{}" server.respond();
]); expect($('#page-notification')).not.toBeEmpty();
$.ajax({ expect($('#page-notification')).toContainElement('div.wrapper-notification-error');
url: "/test", });
notifyOnError: false it('can override AJAX request with error so it does not pop an error notification', function() {
server = AjaxHelpers.server([
500, {
'Content-Type': 'application/json'
}, '{}'
]);
$.ajax({
url: '/test',
notifyOnError: false
});
server.respond();
expect($('#page-notification')).toBeEmpty();
});
}); });
server.respond();
expect($("#page-notification")).toBeEmpty();
}); });
});
});
}).call(this, sandbox); }).call(this, sandbox);
...@@ -24,7 +24,6 @@ define(['jquery', 'backbone', 'xblock/runtime.v1', 'URI', 'gettext', 'js/utils/m ...@@ -24,7 +24,6 @@ define(['jquery', 'backbone', 'xblock/runtime.v1', 'URI', 'gettext', 'js/utils/m
StudioRuntime = {}; StudioRuntime = {};
BaseRuntime.v1 = (function(_super) { BaseRuntime.v1 = (function(_super) {
__extends(v1, _super); __extends(v1, _super);
v1.prototype.handlerUrl = function(element, handlerName, suffix, query) { v1.prototype.handlerUrl = function(element, handlerName, suffix, query) {
...@@ -150,11 +149,9 @@ define(['jquery', 'backbone', 'xblock/runtime.v1', 'URI', 'gettext', 'js/utils/m ...@@ -150,11 +149,9 @@ define(['jquery', 'backbone', 'xblock/runtime.v1', 'URI', 'gettext', 'js/utils/m
}; };
return v1; return v1;
})(XBlock.Runtime.v1); })(XBlock.Runtime.v1);
PreviewRuntime.v1 = (function(_super) { PreviewRuntime.v1 = (function(_super) {
__extends(v1, _super); __extends(v1, _super);
function v1() { function v1() {
...@@ -164,11 +161,9 @@ define(['jquery', 'backbone', 'xblock/runtime.v1', 'URI', 'gettext', 'js/utils/m ...@@ -164,11 +161,9 @@ define(['jquery', 'backbone', 'xblock/runtime.v1', 'URI', 'gettext', 'js/utils/m
v1.prototype.handlerPrefix = '/preview/xblock'; v1.prototype.handlerPrefix = '/preview/xblock';
return v1; return v1;
})(BaseRuntime.v1); })(BaseRuntime.v1);
StudioRuntime.v1 = (function(_super) { StudioRuntime.v1 = (function(_super) {
__extends(v1, _super); __extends(v1, _super);
function v1() { function v1() {
...@@ -178,7 +173,6 @@ define(['jquery', 'backbone', 'xblock/runtime.v1', 'URI', 'gettext', 'js/utils/m ...@@ -178,7 +173,6 @@ define(['jquery', 'backbone', 'xblock/runtime.v1', 'URI', 'gettext', 'js/utils/m
v1.prototype.handlerPrefix = '/xblock'; v1.prototype.handlerPrefix = '/xblock';
return v1; return v1;
})(BaseRuntime.v1); })(BaseRuntime.v1);
// Install the runtime's into the global namespace // Install the runtime's into the global namespace
......
require([ require([
"domReady", 'domReady',
"jquery", 'jquery',
"underscore", 'underscore',
"gettext", 'gettext',
"common/js/components/views/feedback_notification", 'common/js/components/views/feedback_notification',
"common/js/components/views/feedback_prompt", 'common/js/components/views/feedback_prompt',
"js/utils/date_utils", 'js/utils/date_utils',
"js/utils/module", 'js/utils/module',
"js/utils/handle_iframe_binding", 'js/utils/handle_iframe_binding',
"edx-ui-toolkit/js/dropdown-menu/dropdown-menu-view", 'edx-ui-toolkit/js/dropdown-menu/dropdown-menu-view',
"jquery.ui", 'jquery.ui',
"jquery.leanModal", 'jquery.leanModal',
"jquery.form", 'jquery.form',
"jquery.smoothScroll" 'jquery.smoothScroll'
], ],
function( function(
domReady, domReady,
$, $,
...@@ -27,113 +27,110 @@ require([ ...@@ -27,113 +27,110 @@ require([
DropdownMenuView DropdownMenuView
) )
{ {
var $body;
var $body; domReady(function() {
var dropdownMenuView;
domReady(function() { $body = $('body');
var dropdownMenuView;
$body = $('body');
$body.on('click', '.embeddable-xml-input', function() { $body.on('click', '.embeddable-xml-input', function() {
$(this).select(); $(this).select();
}); });
$body.addClass('js'); $body.addClass('js');
// alerts/notifications - manual close // alerts/notifications - manual close
$('.action-alert-close, .alert.has-actions .nav-actions a').bind('click', hideAlert); $('.action-alert-close, .alert.has-actions .nav-actions a').bind('click', hideAlert);
$('.action-notification-close').bind('click', hideNotification); $('.action-notification-close').bind('click', hideNotification);
// nav - dropdown related // nav - dropdown related
$body.click(function(e) { $body.click(function(e) {
$('.nav-dd .nav-item .wrapper-nav-sub').removeClass('is-shown'); $('.nav-dd .nav-item .wrapper-nav-sub').removeClass('is-shown');
$('.nav-dd .nav-item .title').removeClass('is-selected'); $('.nav-dd .nav-item .title').removeClass('is-selected');
}); });
$('.nav-dd .nav-item, .filterable-column .nav-item').click(function(e) { $('.nav-dd .nav-item, .filterable-column .nav-item').click(function(e) {
$subnav = $(this).find('.wrapper-nav-sub');
$title = $(this).find('.title');
$subnav = $(this).find('.wrapper-nav-sub'); if ($subnav.hasClass('is-shown')) {
$title = $(this).find('.title'); $subnav.removeClass('is-shown');
$title.removeClass('is-selected');
if ($subnav.hasClass('is-shown')) { } else {
$subnav.removeClass('is-shown'); $('.nav-dd .nav-item .title').removeClass('is-selected');
$title.removeClass('is-selected'); $('.nav-dd .nav-item .wrapper-nav-sub').removeClass('is-shown');
} else { $title.addClass('is-selected');
$('.nav-dd .nav-item .title').removeClass('is-selected'); $subnav.addClass('is-shown');
$('.nav-dd .nav-item .wrapper-nav-sub').removeClass('is-shown');
$title.addClass('is-selected');
$subnav.addClass('is-shown');
// if propagation is not stopped, the event will bubble up to the // if propagation is not stopped, the event will bubble up to the
// body element, which will close the dropdown. // body element, which will close the dropdown.
e.stopPropagation(); e.stopPropagation();
} }
}); });
// general link management - new window/tab // general link management - new window/tab
$('a[rel="external"]:not([title])').attr('title', gettext('This link will open in a new browser window/tab')); $('a[rel="external"]:not([title])').attr('title', gettext('This link will open in a new browser window/tab'));
$('a[rel="external"]').attr('target', '_blank'); $('a[rel="external"]').attr('target', '_blank');
// general link management - lean modal window // general link management - lean modal window
$('a[rel="modal"]').attr('title', gettext('This link will open in a modal window')).leanModal({ $('a[rel="modal"]').attr('title', gettext('This link will open in a modal window')).leanModal({
overlay: 0.50, overlay: 0.50,
closeButton: '.action-modal-close' closeButton: '.action-modal-close'
}); });
$('.action-modal-close').click(function(e) { $('.action-modal-close').click(function(e) {
(e).preventDefault(); (e).preventDefault();
}); });
// general link management - smooth scrolling page links // general link management - smooth scrolling page links
$('a[rel*="view"][href^="#"]').bind('click', smoothScrollLink); $('a[rel*="view"][href^="#"]').bind('click', smoothScrollLink);
IframeUtils.iframeBinding(); IframeUtils.iframeBinding();
// disable ajax caching in IE so that backbone fetches work // disable ajax caching in IE so that backbone fetches work
if ($.browser.msie) { if ($.browser.msie) {
$.ajaxSetup({ cache: false }); $.ajaxSetup({cache: false});
} }
//Initiate the edx tool kit dropdown menu // Initiate the edx tool kit dropdown menu
if ($('.js-header-user-menu').length){ if ($('.js-header-user-menu').length) {
dropdownMenuView = new DropdownMenuView({ dropdownMenuView = new DropdownMenuView({
el: '.js-header-user-menu' el: '.js-header-user-menu'
});
dropdownMenuView.postRender();
}
}); });
dropdownMenuView.postRender();
} function smoothScrollLink(e) {
}); (e).preventDefault();
function smoothScrollLink(e) { $.smoothScroll({
(e).preventDefault(); offset: -200,
easing: 'swing',
$.smoothScroll({ speed: 1000,
offset: -200, scrollElement: null,
easing: 'swing', scrollTarget: $(this).attr('href')
speed: 1000, });
scrollElement: null, }
scrollTarget: $(this).attr('href')
}); function smoothScrollTop(e) {
} (e).preventDefault();
function smoothScrollTop(e) { $.smoothScroll({
(e).preventDefault(); offset: -200,
easing: 'swing',
$.smoothScroll({ speed: 1000,
offset: -200, scrollElement: null,
easing: 'swing', scrollTarget: $('#view-top')
speed: 1000, });
scrollElement: null, }
scrollTarget: $('#view-top')
}); function hideNotification(e) {
} (e).preventDefault();
$(this).closest('.wrapper-notification').removeClass('is-shown').addClass('is-hiding').attr('aria-hidden', 'true');
function hideNotification(e) { }
(e).preventDefault();
$(this).closest('.wrapper-notification').removeClass('is-shown').addClass('is-hiding').attr('aria-hidden', 'true'); function hideAlert(e) {
} (e).preventDefault();
$(this).closest('.wrapper-alert').removeClass('is-shown');
function hideAlert(e) { }
(e).preventDefault(); }); // end require()
$(this).closest('.wrapper-alert').removeClass('is-shown');
}
}); // end require()
...@@ -29,7 +29,7 @@ function(Backbone, gettext, Certificate) { ...@@ -29,7 +29,7 @@ function(Backbone, gettext, Certificate) {
} catch (ex) { } catch (ex) {
// If it didn't parse, and `certificate_info` is an object then return as it is // If it didn't parse, and `certificate_info` is an object then return as it is
// otherwise return empty array // otherwise return empty array
if (typeof certificate_info === 'object'){ if (typeof certificate_info === 'object') {
return_array = certificate_info; return_array = certificate_info;
} }
else { else {
...@@ -44,28 +44,28 @@ function(Backbone, gettext, Certificate) { ...@@ -44,28 +44,28 @@ function(Backbone, gettext, Certificate) {
return return_array; return return_array;
}, },
onModelRemoved: function () { onModelRemoved: function() {
// remove the certificate web preview UI. // remove the certificate web preview UI.
if(window.certWebPreview && this.length === 0) { if (window.certWebPreview && this.length === 0) {
window.certWebPreview.remove(); window.certWebPreview.remove();
} }
this.toggleAddNewItemButtonState(); this.toggleAddNewItemButtonState();
}, },
onModelAdd: function () { onModelAdd: function() {
this.toggleAddNewItemButtonState(); this.toggleAddNewItemButtonState();
}, },
toggleAddNewItemButtonState: function() { toggleAddNewItemButtonState: function() {
// user can create a new item e.g certificate; if not exceeded the maxAllowed limit. // user can create a new item e.g certificate; if not exceeded the maxAllowed limit.
if(this.length >= this.maxAllowed) { if (this.length >= this.maxAllowed) {
$(".action-add").addClass('action-add-hidden'); $('.action-add').addClass('action-add-hidden');
} else { } else {
$(".action-add").removeClass('action-add-hidden'); $('.action-add').removeClass('action-add-hidden');
} }
}, },
parse: function (certificatesJson) { parse: function(certificatesJson) {
// Transforms the provided JSON into a Certificates collection // Transforms the provided JSON into a Certificates collection
var modelArray = this.certificate_array(certificatesJson); var modelArray = this.certificate_array(certificatesJson);
......
...@@ -20,7 +20,7 @@ define([ ...@@ -20,7 +20,7 @@ define([
], ],
function($, CertificatesCollection, Certificate, CertificatesPage, CertificatePreview) { function($, CertificatesCollection, Certificate, CertificatesPage, CertificatePreview) {
'use strict'; 'use strict';
return function (certificatesJson, certificateUrl, courseOutlineUrl, course_modes, certificate_web_view_url, return function(certificatesJson, certificateUrl, courseOutlineUrl, course_modes, certificate_web_view_url,
is_active, certificate_activation_handler_url) { is_active, certificate_activation_handler_url) {
// Initialize the model collection, passing any necessary options to the constructor // Initialize the model collection, passing any necessary options to the constructor
var certificatesCollection = new CertificatesCollection(certificatesJson, { var certificatesCollection = new CertificatesCollection(certificatesJson, {
...@@ -31,7 +31,7 @@ function($, CertificatesCollection, Certificate, CertificatesPage, CertificatePr ...@@ -31,7 +31,7 @@ function($, CertificatesCollection, Certificate, CertificatesPage, CertificatePr
// associating the certificate_preview globally. // associating the certificate_preview globally.
// need to show / hide this view in some other places. // need to show / hide this view in some other places.
if(!window.certWebPreview && certificate_web_view_url) { if (!window.certWebPreview && certificate_web_view_url) {
window.certWebPreview = new CertificatePreview({ window.certWebPreview = new CertificatePreview({
course_modes: course_modes, course_modes: course_modes,
certificate_web_view_url: certificate_web_view_url, certificate_web_view_url: certificate_web_view_url,
......
// Backbone.js Application Model: Certificate // Backbone.js Application Model: Certificate
define([ define([
'underscore', 'underscore',
'backbone', 'backbone',
'backbone-relational', 'backbone-relational',
'backbone.associations', 'backbone.associations',
'gettext', 'gettext',
'cms/js/main', 'cms/js/main',
'js/certificates/models/signatory', 'js/certificates/models/signatory',
'js/certificates/collections/signatories' 'js/certificates/collections/signatories'
], ],
function(_, Backbone, BackboneRelational, BackboneAssociations, gettext, CoffeeSrcMain, function(_, Backbone, BackboneRelational, BackboneAssociations, gettext, CoffeeSrcMain,
SignatoryModel, SignatoryCollection) { SignatoryModel, SignatoryCollection) {
'use strict'; 'use strict';
...@@ -78,7 +78,7 @@ define([ ...@@ -78,7 +78,7 @@ define([
attributes: {name: true} attributes: {name: true}
}; };
} }
var allSignatoriesValid = _.every(attrs.signatories.models, function(signatory){ var allSignatoriesValid = _.every(attrs.signatories.models, function(signatory) {
return signatory.isValid(); return signatory.isValid();
}); });
if (!allSignatoriesValid) { if (!allSignatoriesValid) {
......
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
define(['jquery'], function($) { // eslint-disable-line no-unused-vars define(['jquery'], function($) { // eslint-disable-line no-unused-vars
'use strict'; 'use strict';
return function () { return function() {
jasmine.addMatchers({ jasmine.addMatchers({
toBeCorrectValuesInModel: function () { toBeCorrectValuesInModel: function() {
// Assert the value being tested has key values which match the provided values // Assert the value being tested has key values which match the provided values
return { return {
compare: function (actual, values) { compare: function(actual, values) {
var passed = _.every(values, function (value, key) { var passed = _.every(values, function(value, key) {
return actual.get(key) === value; return actual.get(key) === value;
}.bind(this)); }.bind(this));
......
...@@ -11,7 +11,7 @@ function(CertificateModel, CertificateCollection) { ...@@ -11,7 +11,7 @@ function(CertificateModel, CertificateCollection) {
beforeEach(function() { beforeEach(function() {
this.newModelOptions = {add: true}; this.newModelOptions = {add: true};
this.model = new CertificateModel({editing: true}, this.newModelOptions); this.model = new CertificateModel({editing: true}, this.newModelOptions);
this.collection = new CertificateCollection([ this.model ], {certificateUrl: '/outline'}); this.collection = new CertificateCollection([this.model], {certificateUrl: '/outline'});
}); });
describe('Basic', function() { describe('Basic', function() {
...@@ -39,18 +39,16 @@ function(CertificateModel, CertificateCollection) { ...@@ -39,18 +39,16 @@ function(CertificateModel, CertificateCollection) {
describe('Validation', function() { describe('Validation', function() {
it('requires a name', function() { it('requires a name', function() {
var model = new CertificateModel({ name: '' }, this.newModelOptions); var model = new CertificateModel({name: ''}, this.newModelOptions);
expect(model.isValid()).toBeFalsy(); expect(model.isValid()).toBeFalsy();
}); });
it('can pass validation', function() { it('can pass validation', function() {
var model = new CertificateModel({ name: 'foo' }, this.newModelOptions); var model = new CertificateModel({name: 'foo'}, this.newModelOptions);
expect(model.isValid()).toBeTruthy(); expect(model.isValid()).toBeTruthy();
}); });
}); });
}); });
}); });
...@@ -41,15 +41,15 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails ...@@ -41,15 +41,15 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails
inputSignatoryTitle: '.signatory-title-input', inputSignatoryTitle: '.signatory-title-input',
inputSignatoryOrganization: '.signatory-organization-input' inputSignatoryOrganization: '.signatory-organization-input'
}; };
var verifyAndConfirmPrompt = function(promptSpy, promptText){ var verifyAndConfirmPrompt = function(promptSpy, promptText) {
ViewHelpers.verifyPromptShowing(promptSpy, gettext(promptText)); ViewHelpers.verifyPromptShowing(promptSpy, gettext(promptText));
ViewHelpers.confirmPrompt(promptSpy); ViewHelpers.confirmPrompt(promptSpy);
ViewHelpers.verifyPromptHidden(promptSpy); ViewHelpers.verifyPromptHidden(promptSpy);
}; };
describe('Certificate Details Spec:', function() { describe('Certificate Details Spec:', function() {
var setValuesToInputs = function (view, values) { var setValuesToInputs = function(view, values) {
_.each(values, function (value, selector) { _.each(values, function(value, selector) {
if (SELECTORS[selector]) { if (SELECTORS[selector]) {
view.$(SELECTORS[selector]).val(value); view.$(SELECTORS[selector]).val(value);
view.$(SELECTORS[selector]).trigger('change'); view.$(SELECTORS[selector]).trigger('change');
...@@ -96,8 +96,8 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails ...@@ -96,8 +96,8 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails
is_active: true is_active: true
}, this.newModelOptions); }, this.newModelOptions);
this.collection = new CertificatesCollection([ this.model ], { this.collection = new CertificatesCollection([this.model], {
certificateUrl: '/certificates/'+ window.course.id certificateUrl: '/certificates/' + window.course.id
}); });
this.model.set('id', 0); this.model.set('id', 0);
this.view = new CertificateDetailsView({ this.view = new CertificateDetailsView({
...@@ -120,44 +120,43 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails ...@@ -120,44 +120,43 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails
describe('The Certificate Details view', function() { describe('The Certificate Details view', function() {
it('should parse a JSON string collection into a Backbone model collection', function() {
it('should parse a JSON string collection into a Backbone model collection', function () { var course_title = 'Test certificate course title override 2';
var course_title = "Test certificate course title override 2";
var CERTIFICATE_JSON = '[{"course_title": "' + course_title + '", "signatories":"[]"}]'; var CERTIFICATE_JSON = '[{"course_title": "' + course_title + '", "signatories":"[]"}]';
this.collection.parse(CERTIFICATE_JSON); this.collection.parse(CERTIFICATE_JSON);
var model = this.collection.at(1); var model = this.collection.at(1);
expect(model.get('course_title')).toEqual(course_title); expect(model.get('course_title')).toEqual(course_title);
}); });
it('should parse a JSON object collection into a Backbone model collection', function () { it('should parse a JSON object collection into a Backbone model collection', function() {
var course_title = "Test certificate course title override 2"; var course_title = 'Test certificate course title override 2';
var CERTIFICATE_JSON_OBJECT = [{ var CERTIFICATE_JSON_OBJECT = [{
"course_title" : course_title, 'course_title': course_title,
"signatories" : "[]" 'signatories': '[]'
}]; }];
this.collection.parse(CERTIFICATE_JSON_OBJECT); this.collection.parse(CERTIFICATE_JSON_OBJECT);
var model = this.collection.at(1); var model = this.collection.at(1);
expect(model.get('course_title')).toEqual(course_title); expect(model.get('course_title')).toEqual(course_title);
}); });
it('should have empty certificate collection if there is an error parsing certifcate JSON', function () { it('should have empty certificate collection if there is an error parsing certifcate JSON', function() {
var CERTIFICATE_INVALID_JSON = '[{"course_title": Test certificate course title override, "signatories":"[]"}]'; // eslint-disable-line max-len var CERTIFICATE_INVALID_JSON = '[{"course_title": Test certificate course title override, "signatories":"[]"}]'; // eslint-disable-line max-len
var collection_length = this.collection.length; var collection_length = this.collection.length;
this.collection.parse(CERTIFICATE_INVALID_JSON); this.collection.parse(CERTIFICATE_INVALID_JSON);
//collection length should remain the same since we have error parsing JSON // collection length should remain the same since we have error parsing JSON
expect(this.collection.length).toEqual(collection_length); expect(this.collection.length).toEqual(collection_length);
}); });
it('should display the certificate course title override', function () { it('should display the certificate course title override', function() {
expect(this.view.$(SELECTORS.course_title)).toExist(); expect(this.view.$(SELECTORS.course_title)).toExist();
expect(this.view.$(SELECTORS.course_title)).toContainText('Test Course Title Override'); expect(this.view.$(SELECTORS.course_title)).toContainText('Test Course Title Override');
}); });
it('should present an Edit action', function () { it('should present an Edit action', function() {
expect(this.view.$('.edit')).toExist(); expect(this.view.$('.edit')).toExist();
}); });
it('should change to "edit" mode when clicking the Edit button and confirming the prompt', function(){ it('should change to "edit" mode when clicking the Edit button and confirming the prompt', function() {
expect(this.view.$('.action-edit .edit')).toExist(); expect(this.view.$('.action-edit .edit')).toExist();
var promptSpy = ViewHelpers.createPromptSpy(); var promptSpy = ViewHelpers.createPromptSpy();
this.view.$('.action-edit .edit').click(); this.view.$('.action-edit .edit').click();
...@@ -165,67 +164,64 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails ...@@ -165,67 +164,64 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails
expect(this.model.get('editing')).toBe(true); expect(this.model.get('editing')).toBe(true);
}); });
it('should not show confirmation prompt when clicked on "edit" in case of inactive certificate', function(){ it('should not show confirmation prompt when clicked on "edit" in case of inactive certificate', function() {
this.model.set('is_active', false); this.model.set('is_active', false);
expect(this.view.$('.action-edit .edit')).toExist(); expect(this.view.$('.action-edit .edit')).toExist();
this.view.$('.action-edit .edit').click(); this.view.$('.action-edit .edit').click();
expect(this.model.get('editing')).toBe(true); expect(this.model.get('editing')).toBe(true);
}); });
it('should not present a Edit action if user is not global staff and certificate is active', function () { it('should not present a Edit action if user is not global staff and certificate is active', function() {
window.CMS.User = {isGlobalStaff: false}; window.CMS.User = {isGlobalStaff: false};
appendSetFixtures(this.view.render().el); appendSetFixtures(this.view.render().el);
expect(this.view.$('.action-edit .edit')).not.toExist(); expect(this.view.$('.action-edit .edit')).not.toExist();
}); });
it('should present a Delete action', function () { it('should present a Delete action', function() {
expect(this.view.$('.action-delete .delete')).toExist(); expect(this.view.$('.action-delete .delete')).toExist();
}); });
it('should not present a Delete action if user is not global staff and certificate is active', function () { it('should not present a Delete action if user is not global staff and certificate is active', function() {
window.CMS.User = {isGlobalStaff: false}; window.CMS.User = {isGlobalStaff: false};
appendSetFixtures(this.view.render().el); appendSetFixtures(this.view.render().el);
expect(this.view.$('.action-delete .delete')).not.toExist(); expect(this.view.$('.action-delete .delete')).not.toExist();
}); });
it('should prompt the user when when clicking the Delete button', function(){ it('should prompt the user when when clicking the Delete button', function() {
expect(this.view.$('.action-delete .delete')).toExist(); expect(this.view.$('.action-delete .delete')).toExist();
this.view.$('.action-delete .delete').click(); this.view.$('.action-delete .delete').click();
}); });
it('should scroll to top after rendering if necessary', function () { it('should scroll to top after rendering if necessary', function() {
$.smoothScroll = jasmine.createSpy('jQuery.smoothScroll'); $.smoothScroll = jasmine.createSpy('jQuery.smoothScroll');
appendSetFixtures(this.view.render().el); appendSetFixtures(this.view.render().el);
expect($.smoothScroll).toHaveBeenCalled(); expect($.smoothScroll).toHaveBeenCalled();
}); });
}); });
describe('Signatory details', function(){ describe('Signatory details', function() {
beforeEach(function() { beforeEach(function() {
this.view.render(); this.view.render();
}); });
it('displays certificate signatories details', function(){ it('displays certificate signatories details', function() {
this.view.$('.show-details').click(); this.view.$('.show-details').click();
expect(this.view.$(SELECTORS.signatory_name_value)).toContainText(''); expect(this.view.$(SELECTORS.signatory_name_value)).toContainText('');
expect(this.view.$(SELECTORS.signatory_title_value)).toContainText(''); expect(this.view.$(SELECTORS.signatory_title_value)).toContainText('');
expect(this.view.$(SELECTORS.signatory_organization_value)).toContainText(''); expect(this.view.$(SELECTORS.signatory_organization_value)).toContainText('');
}); });
it('should present Edit action on signaotry', function () { it('should present Edit action on signaotry', function() {
expect(this.view.$(SELECTORS.edit_signatory)).toExist(); expect(this.view.$(SELECTORS.edit_signatory)).toExist();
}); });
it('should not present Edit action on signaotry if user is not global staff and certificate is active', function () { it('should not present Edit action on signaotry if user is not global staff and certificate is active', function() {
window.CMS.User = {isGlobalStaff: false}; window.CMS.User = {isGlobalStaff: false};
this.view.render(); this.view.render();
expect(this.view.$(SELECTORS.edit_signatory)).not.toExist(); expect(this.view.$(SELECTORS.edit_signatory)).not.toExist();
}); });
it('supports in-line editing of signatory information', function() { it('supports in-line editing of signatory information', function() {
this.view.$(SELECTORS.edit_signatory).click(); this.view.$(SELECTORS.edit_signatory).click();
expect(this.view.$(SELECTORS.inputSignatoryName)).toExist(); expect(this.view.$(SELECTORS.inputSignatoryName)).toExist();
expect(this.view.$(SELECTORS.inputSignatoryTitle)).toExist(); expect(this.view.$(SELECTORS.inputSignatoryTitle)).toExist();
...@@ -233,7 +229,6 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails ...@@ -233,7 +229,6 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails
}); });
it('correctly persists changes made during in-line signatory editing', function() { it('correctly persists changes made during in-line signatory editing', function() {
var requests = AjaxHelpers.requests(this), var requests = AjaxHelpers.requests(this),
notificationSpy = ViewHelpers.createNotificationSpy(); notificationSpy = ViewHelpers.createNotificationSpy();
......
...@@ -37,14 +37,14 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -37,14 +37,14 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
note: '.wrapper-delete-button', note: '.wrapper-delete-button',
addSignatoryButton: '.action-add-signatory', addSignatoryButton: '.action-add-signatory',
signatoryDeleteButton: '.signatory-panel-delete', signatoryDeleteButton: '.signatory-panel-delete',
uploadSignatureButton:'.action-upload-signature', uploadSignatureButton: '.action-upload-signature',
uploadDialog: 'form.upload-dialog', uploadDialog: 'form.upload-dialog',
uploadDialogButton: '.action-upload', uploadDialogButton: '.action-upload',
uploadDialogFileInput: 'form.upload-dialog input[type=file]', uploadDialogFileInput: 'form.upload-dialog input[type=file]',
saveCertificateButton: 'button.action-primary' saveCertificateButton: 'button.action-primary'
}; };
var clickDeleteItem = function (that, promptText, element, url) { var clickDeleteItem = function(that, promptText, element, url) {
var requests = AjaxHelpers.requests(that), var requests = AjaxHelpers.requests(that),
promptSpy = ViewHelpers.createPromptSpy(), promptSpy = ViewHelpers.createPromptSpy(),
notificationSpy = ViewHelpers.createNotificationSpy(); notificationSpy = ViewHelpers.createNotificationSpy();
...@@ -53,7 +53,7 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -53,7 +53,7 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
ViewHelpers.verifyPromptShowing(promptSpy, promptText); ViewHelpers.verifyPromptShowing(promptSpy, promptText);
ViewHelpers.confirmPrompt(promptSpy); ViewHelpers.confirmPrompt(promptSpy);
ViewHelpers.verifyPromptHidden(promptSpy); ViewHelpers.verifyPromptHidden(promptSpy);
if (!_.isUndefined(url) && !_.isEmpty(url)){ if (!_.isUndefined(url) && !_.isEmpty(url)) {
AjaxHelpers.expectJsonRequest(requests, 'POST', url); AjaxHelpers.expectJsonRequest(requests, 'POST', url);
expect(_.last(requests).requestHeaders['X-HTTP-Method-Override']).toBe('DELETE'); expect(_.last(requests).requestHeaders['X-HTTP-Method-Override']).toBe('DELETE');
ViewHelpers.verifyNotificationShowing(notificationSpy, /Deleting/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Deleting/);
...@@ -62,7 +62,7 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -62,7 +62,7 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
} }
}; };
var showConfirmPromptAndClickCancel = function (view, element, promptText) { var showConfirmPromptAndClickCancel = function(view, element, promptText) {
var promptSpy = ViewHelpers.createPromptSpy(); var promptSpy = ViewHelpers.createPromptSpy();
view.$(element).click(); view.$(element).click();
ViewHelpers.verifyPromptShowing(promptSpy, promptText); ViewHelpers.verifyPromptShowing(promptSpy, promptText);
...@@ -70,15 +70,15 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -70,15 +70,15 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
ViewHelpers.verifyPromptHidden(promptSpy); ViewHelpers.verifyPromptHidden(promptSpy);
}; };
var uploadFile = function (file_path, requests){ var uploadFile = function(file_path, requests) {
$(SELECTORS.uploadDialogFileInput).change(); $(SELECTORS.uploadDialogFileInput).change();
$(SELECTORS.uploadDialogButton).click(); $(SELECTORS.uploadDialogButton).click();
AjaxHelpers.respondWithJson(requests, {asset: {url: file_path}}); AjaxHelpers.respondWithJson(requests, {asset: {url: file_path}});
}; };
describe('Certificate editor view', function() { describe('Certificate editor view', function() {
var setValuesToInputs = function (view, values) { var setValuesToInputs = function(view, values) {
_.each(values, function (value, selector) { _.each(values, function(value, selector) {
if (SELECTORS[selector]) { if (SELECTORS[selector]) {
view.$(SELECTORS[selector]).val(value); view.$(SELECTORS[selector]).val(value);
view.$(SELECTORS[selector]).trigger('change'); view.$(SELECTORS[selector]).trigger('change');
...@@ -86,8 +86,8 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -86,8 +86,8 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
}); });
}; };
var basicModalTpl = readFixtures('basic-modal.underscore'), var basicModalTpl = readFixtures('basic-modal.underscore'),
modalButtonTpl = readFixtures('modal-button.underscore'), modalButtonTpl = readFixtures('modal-button.underscore'),
uploadDialogTpl = readFixtures('upload-dialog.underscore'); uploadDialogTpl = readFixtures('upload-dialog.underscore');
beforeEach(function() { beforeEach(function() {
TemplateHelpers.installTemplates(['certificate-editor', 'signatory-editor'], true); TemplateHelpers.installTemplates(['certificate-editor', 'signatory-editor'], true);
...@@ -110,8 +110,8 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -110,8 +110,8 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
}, this.newModelOptions); }, this.newModelOptions);
this.collection = new CertificatesCollection([ this.model ], { this.collection = new CertificatesCollection([this.model], {
certificateUrl: '/certificates/'+ window.course.id certificateUrl: '/certificates/' + window.course.id
}); });
this.model.set('id', 0); this.model.set('id', 0);
this.view = new CertificateEditorView({ this.view = new CertificateEditorView({
...@@ -127,20 +127,20 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -127,20 +127,20 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
delete window.CMS.User; delete window.CMS.User;
}); });
describe('Basic', function () { describe('Basic', function() {
beforeEach(function(){ beforeEach(function() {
appendSetFixtures( appendSetFixtures(
$("<script>", { id: "basic-modal-tpl", type: "text/template" }).text(basicModalTpl) $('<script>', {id: 'basic-modal-tpl', type: 'text/template'}).text(basicModalTpl)
); );
appendSetFixtures( appendSetFixtures(
$("<script>", { id: "modal-button-tpl", type: "text/template" }).text(modalButtonTpl) $('<script>', {id: 'modal-button-tpl', type: 'text/template'}).text(modalButtonTpl)
); );
appendSetFixtures( appendSetFixtures(
$("<script>", { id: "upload-dialog-tpl", type: "text/template" }).text(uploadDialogTpl) $('<script>', {id: 'upload-dialog-tpl', type: 'text/template'}).text(uploadDialogTpl)
); );
}); });
afterEach(function(){ afterEach(function() {
$('.wrapper-modal-window-assetupload').remove(); $('.wrapper-modal-window-assetupload').remove();
}); });
...@@ -198,11 +198,10 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -198,11 +198,10 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
}); });
it('user can only add signatories up to limit', function() { it('user can only add signatories up to limit', function() {
for(var i = 1; i < MAX_SIGNATORIES_LIMIT ; i++) { for (var i = 1; i < MAX_SIGNATORIES_LIMIT; i++) {
this.view.$(SELECTORS.addSignatoryButton).click(); this.view.$(SELECTORS.addSignatoryButton).click();
} }
expect(this.view.$(SELECTORS.addSignatoryButton)).toHaveClass('disableClick'); expect(this.view.$(SELECTORS.addSignatoryButton)).toHaveClass('disableClick');
}); });
it('user can add signatories if not reached the upper limit', function() { it('user can add signatories if not reached the upper limit', function() {
...@@ -214,14 +213,14 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -214,14 +213,14 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
it('user can add signatories when signatory reached the upper limit But after deleting a signatory', it('user can add signatories when signatory reached the upper limit But after deleting a signatory',
function() { function() {
for(var i = 1; i < MAX_SIGNATORIES_LIMIT ; i++) { for (var i = 1; i < MAX_SIGNATORIES_LIMIT; i++) {
this.view.$(SELECTORS.addSignatoryButton).click(); this.view.$(SELECTORS.addSignatoryButton).click();
} }
expect(this.view.$(SELECTORS.addSignatoryButton)).toHaveClass('disableClick'); expect(this.view.$(SELECTORS.addSignatoryButton)).toHaveClass('disableClick');
// now delete anyone of the signatory, Add signatory should be enabled. // now delete anyone of the signatory, Add signatory should be enabled.
var signatory = this.model.get('signatories').at(0); var signatory = this.model.get('signatories').at(0);
var text = 'Delete "'+ signatory.get('name') +'" from the list of signatories?'; var text = 'Delete "' + signatory.get('name') + '" from the list of signatories?';
clickDeleteItem(this, text, SELECTORS.signatoryDeleteButton + ':first'); clickDeleteItem(this, text, SELECTORS.signatoryDeleteButton + ':first');
expect(this.view.$(SELECTORS.addSignatoryButton)).not.toHaveClass('disableClick'); expect(this.view.$(SELECTORS.addSignatoryButton)).not.toHaveClass('disableClick');
} }
...@@ -273,8 +272,8 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -273,8 +272,8 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
var signatory = this.model.get('signatories').at(0); var signatory = this.model.get('signatories').at(0);
var signatory_url = '/certificates/signatory'; var signatory_url = '/certificates/signatory';
signatory.url = signatory_url; signatory.url = signatory_url;
spyOn(signatory, "isNew").and.returnValue(false); spyOn(signatory, 'isNew').and.returnValue(false);
var text = 'Delete "'+ signatory.get('name') +'" from the list of signatories?'; var text = 'Delete "' + signatory.get('name') + '" from the list of signatories?';
clickDeleteItem(this, text, SELECTORS.signatoryDeleteButton + ':first', signatory_url); clickDeleteItem(this, text, SELECTORS.signatoryDeleteButton + ':first', signatory_url);
expect(this.model.get('signatories').length).toEqual(total_signatories - 1); expect(this.model.get('signatories').length).toEqual(total_signatories - 1);
}); });
...@@ -282,13 +281,13 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce ...@@ -282,13 +281,13 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
it('can cancel deletion of signatories', function() { it('can cancel deletion of signatories', function() {
this.view.$(SELECTORS.addSignatoryButton).click(); this.view.$(SELECTORS.addSignatoryButton).click();
var signatory = this.model.get('signatories').at(0); var signatory = this.model.get('signatories').at(0);
spyOn(signatory, "isNew").and.returnValue(false); spyOn(signatory, 'isNew').and.returnValue(false);
// add one more signatory // add one more signatory
this.view.$(SELECTORS.addSignatoryButton).click(); this.view.$(SELECTORS.addSignatoryButton).click();
var total_signatories = this.model.get('signatories').length; var total_signatories = this.model.get('signatories').length;
var signatory_url = '/certificates/signatory'; var signatory_url = '/certificates/signatory';
signatory.url = signatory_url; signatory.url = signatory_url;
var text = 'Delete "'+ signatory.get('name') +'" from the list of signatories?'; var text = 'Delete "' + signatory.get('name') + '" from the list of signatories?';
showConfirmPromptAndClickCancel(this.view, SELECTORS.signatoryDeleteButton + ':first', text); showConfirmPromptAndClickCancel(this.view, SELECTORS.signatoryDeleteButton + ':first', text);
expect(this.model.get('signatories').length).toEqual(total_signatories); expect(this.model.get('signatories').length).toEqual(total_signatories);
}); });
......
...@@ -19,8 +19,7 @@ function(_, $, Course, CertificatePreview, TemplateHelpers, ViewHelpers, AjaxHel ...@@ -19,8 +19,7 @@ function(_, $, Course, CertificatePreview, TemplateHelpers, ViewHelpers, AjaxHel
}; };
describe('Certificate Web Preview Spec:', function() { describe('Certificate Web Preview Spec:', function() {
var selectDropDownByText = function(element, value) {
var selectDropDownByText = function ( element, value ) {
if (value) { if (value) {
element.val(value); element.val(value);
element.trigger('change'); element.trigger('change');
...@@ -44,7 +43,7 @@ function(_, $, Course, CertificatePreview, TemplateHelpers, ViewHelpers, AjaxHel ...@@ -44,7 +43,7 @@ function(_, $, Course, CertificatePreview, TemplateHelpers, ViewHelpers, AjaxHel
el: $('.preview-certificate'), el: $('.preview-certificate'),
course_modes: ['test1', 'test2', 'test3'], course_modes: ['test1', 'test2', 'test3'],
certificate_web_view_url: '/users/1/courses/orgX/009/2016?preview=test1', certificate_web_view_url: '/users/1/courses/orgX/009/2016?preview=test1',
certificate_activation_handler_url: '/certificates/activation/'+ window.course.id, certificate_activation_handler_url: '/certificates/activation/' + window.course.id,
is_active: true is_active: true
}); });
appendSetFixtures(this.view.render().el); appendSetFixtures(this.view.render().el);
...@@ -56,14 +55,14 @@ function(_, $, Course, CertificatePreview, TemplateHelpers, ViewHelpers, AjaxHel ...@@ -56,14 +55,14 @@ function(_, $, Course, CertificatePreview, TemplateHelpers, ViewHelpers, AjaxHel
}); });
describe('Certificate preview', function() { describe('Certificate preview', function() {
it('course mode event should call when user choose a new mode', function () { it('course mode event should call when user choose a new mode', function() {
spyOn(this.view, 'courseModeChanged'); spyOn(this.view, 'courseModeChanged');
this.view.delegateEvents(); this.view.delegateEvents();
selectDropDownByText(this.view.$(SELECTORS.course_modes), 'test3'); selectDropDownByText(this.view.$(SELECTORS.course_modes), 'test3');
expect(this.view.courseModeChanged).toHaveBeenCalled(); expect(this.view.courseModeChanged).toHaveBeenCalled();
}); });
it('course mode selection updating the link successfully', function () { it('course mode selection updating the link successfully', function() {
selectDropDownByText(this.view.$(SELECTORS.course_modes), 'test1'); selectDropDownByText(this.view.$(SELECTORS.course_modes), 'test1');
expect(this.view.$(SELECTORS.preview_certificate).attr('href')). expect(this.view.$(SELECTORS.preview_certificate).attr('href')).
toEqual('/users/1/courses/orgX/009/2016?preview=test1'); toEqual('/users/1/courses/orgX/009/2016?preview=test1');
...@@ -77,54 +76,52 @@ function(_, $, Course, CertificatePreview, TemplateHelpers, ViewHelpers, AjaxHel ...@@ -77,54 +76,52 @@ function(_, $, Course, CertificatePreview, TemplateHelpers, ViewHelpers, AjaxHel
toEqual('/users/1/courses/orgX/009/2016?preview=test3'); toEqual('/users/1/courses/orgX/009/2016?preview=test3');
}); });
it('toggle certificate activation event works fine', function () { it('toggle certificate activation event works fine', function() {
spyOn(this.view, 'toggleCertificateActivation'); spyOn(this.view, 'toggleCertificateActivation');
this.view.delegateEvents(); this.view.delegateEvents();
this.view.$(SELECTORS.activate_certificate).click(); this.view.$(SELECTORS.activate_certificate).click();
expect(this.view.toggleCertificateActivation).toHaveBeenCalled(); expect(this.view.toggleCertificateActivation).toHaveBeenCalled();
}); });
it('toggle certificate activation button should not be present if user is not global staff', function () { it('toggle certificate activation button should not be present if user is not global staff', function() {
window.CMS.User = {isGlobalStaff: false}; window.CMS.User = {isGlobalStaff: false};
appendSetFixtures(this.view.render().el); appendSetFixtures(this.view.render().el);
expect(this.view.$(SELECTORS.activate_certificate)).not.toExist(); expect(this.view.$(SELECTORS.activate_certificate)).not.toExist();
}); });
it('certificate deactivation works fine', function () { it('certificate deactivation works fine', function() {
var requests = AjaxHelpers.requests(this), var requests = AjaxHelpers.requests(this),
notificationSpy = ViewHelpers.createNotificationSpy(); notificationSpy = ViewHelpers.createNotificationSpy();
this.view.$(SELECTORS.activate_certificate).click(); this.view.$(SELECTORS.activate_certificate).click();
AjaxHelpers.expectJsonRequest(requests, 'POST', '/certificates/activation/'+ window.course.id, { AjaxHelpers.expectJsonRequest(requests, 'POST', '/certificates/activation/' + window.course.id, {
is_active: false is_active: false
}); });
ViewHelpers.verifyNotificationShowing(notificationSpy, /Deactivating/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Deactivating/);
}); });
it('certificate activation works fine', function () { it('certificate activation works fine', function() {
var requests = AjaxHelpers.requests(this), var requests = AjaxHelpers.requests(this),
notificationSpy = ViewHelpers.createNotificationSpy(); notificationSpy = ViewHelpers.createNotificationSpy();
this.view.is_active = false; this.view.is_active = false;
this.view.$(SELECTORS.activate_certificate).click(); this.view.$(SELECTORS.activate_certificate).click();
AjaxHelpers.expectJsonRequest(requests, 'POST', '/certificates/activation/'+ window.course.id, { AjaxHelpers.expectJsonRequest(requests, 'POST', '/certificates/activation/' + window.course.id, {
is_active: true is_active: true
}); });
ViewHelpers.verifyNotificationShowing(notificationSpy, /Activating/); ViewHelpers.verifyNotificationShowing(notificationSpy, /Activating/);
}); });
it('certificate should be deactivate when method "remove" called', function () { it('certificate should be deactivate when method "remove" called', function() {
this.view.remove(); this.view.remove();
expect(this.view.is_active).toBe(false); expect(this.view.is_active).toBe(false);
}); });
it('certificate web preview should be removed when method "remove" called', function () { it('certificate web preview should be removed when method "remove" called', function() {
this.view.remove(); this.view.remove();
expect(this.view.el.innerHTML).toBe(''); expect(this.view.el.innerHTML).toBe('');
}); });
it('method "show" should call the render function', function () { it('method "show" should call the render function', function() {
spyOn(this.view, "render"); spyOn(this.view, 'render');
this.view.show(); this.view.show();
expect(this.view.render).toHaveBeenCalled(); expect(this.view.render).toHaveBeenCalled();
}); });
......
...@@ -16,7 +16,7 @@ define([ ...@@ -16,7 +16,7 @@ define([
'js/certificates/spec/custom_matchers' 'js/certificates/spec/custom_matchers'
], ],
function(_, Course, CertificatesCollection, CertificateModel, CertificateDetailsView, CertificateEditorView, function(_, Course, CertificatesCollection, CertificateModel, CertificateDetailsView, CertificateEditorView,
CertificateItemView, CertificatesListView, CertificatePreview, Notification, AjaxHelpers, TemplateHelpers, CertificateItemView, CertificatesListView, CertificatePreview, Notification, AjaxHelpers, TemplateHelpers,
CustomMatchers) { CustomMatchers) {
'use strict'; 'use strict';
...@@ -54,7 +54,7 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails ...@@ -54,7 +54,7 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails
}, {add: true}); }, {add: true});
this.collection = new CertificatesCollection([], { this.collection = new CertificatesCollection([], {
certificateUrl: '/certificates/'+ window.course.id certificateUrl: '/certificates/' + window.course.id
}); });
this.model.set('id', 0); this.model.set('id', 0);
this.view = new CertificatesListView({ this.view = new CertificatesListView({
...@@ -70,7 +70,7 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails ...@@ -70,7 +70,7 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails
delete window.CMS.User; delete window.CMS.User;
}); });
describe('empty template', function () { describe('empty template', function() {
it('should be rendered if no certificates', function() { it('should be rendered if no certificates', function() {
expect(this.view.$(SELECTORS.noContent)).toExist(); expect(this.view.$(SELECTORS.noContent)).toExist();
expect(this.view.$(SELECTORS.noContent)).toContainText(emptyMessage); expect(this.view.$(SELECTORS.noContent)).toContainText(emptyMessage);
...@@ -99,7 +99,6 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails ...@@ -99,7 +99,6 @@ function(_, Course, CertificatesCollection, CertificateModel, CertificateDetails
this.collection.add(this.model); this.collection.add(this.model);
expect(this.view.$(SELECTORS.itemEditView)).toExist(); expect(this.view.$(SELECTORS.itemEditView)).toExist();
}); });
}); });
}); });
}); });
...@@ -21,7 +21,7 @@ function($, _, str, gettext, BaseView, SignatoryModel, SignatoryDetailsView, Vie ...@@ -21,7 +21,7 @@ function($, _, str, gettext, BaseView, SignatoryModel, SignatoryDetailsView, Vie
'click .edit': 'editCertificate' 'click .edit': 'editCertificate'
}, },
className: function () { className: function() {
// Determine the CSS class names for this model instance // Determine the CSS class names for this model instance
return [ return [
'collection', 'collection',
...@@ -40,7 +40,7 @@ function($, _, str, gettext, BaseView, SignatoryModel, SignatoryDetailsView, Vie ...@@ -40,7 +40,7 @@ function($, _, str, gettext, BaseView, SignatoryModel, SignatoryDetailsView, Vie
// Flip the model into 'editing' mode // Flip the model into 'editing' mode
if (event && event.preventDefault) { event.preventDefault(); } if (event && event.preventDefault) { event.preventDefault(); }
var self = this; var self = this;
if (this.model.get("is_active") === true){ if (this.model.get('is_active') === true) {
ViewUtils.confirmThenRunOperation( ViewUtils.confirmThenRunOperation(
gettext('Edit this certificate?'), gettext('Edit this certificate?'),
gettext('This certificate has already been activated and is live. Are you sure you want to continue editing?'), gettext('This certificate has already been activated and is live. Are you sure you want to continue editing?'),
...@@ -50,7 +50,7 @@ function($, _, str, gettext, BaseView, SignatoryModel, SignatoryDetailsView, Vie ...@@ -50,7 +50,7 @@ function($, _, str, gettext, BaseView, SignatoryModel, SignatoryDetailsView, Vie
} }
); );
} }
else{ else {
this.model.set('editing', true); this.model.set('editing', true);
} }
}, },
...@@ -63,15 +63,15 @@ function($, _, str, gettext, BaseView, SignatoryModel, SignatoryDetailsView, Vie ...@@ -63,15 +63,15 @@ function($, _, str, gettext, BaseView, SignatoryModel, SignatoryDetailsView, Vie
showDetails: this.showDetails || showDetails || false showDetails: this.showDetails || showDetails || false
}); });
this.$el.html(_.template(certificateDetailsTemplate)(attrs)); this.$el.html(_.template(certificateDetailsTemplate)(attrs));
if(this.showDetails || showDetails) { if (this.showDetails || showDetails) {
var self = this; var self = this;
this.model.get("signatories").each(function (modelSignatory) { this.model.get('signatories').each(function(modelSignatory) {
var signatory_detail_view = new SignatoryDetailsView({model: modelSignatory}); var signatory_detail_view = new SignatoryDetailsView({model: modelSignatory});
self.$('div.signatory-details-list').append($(signatory_detail_view.render().$el)); self.$('div.signatory-details-list').append($(signatory_detail_view.render().$el));
}); });
} }
if(this.model.collection.length > 0 && window.certWebPreview) { if (this.model.collection.length > 0 && window.certWebPreview) {
window.certWebPreview.show(); window.certWebPreview.show();
} }
$.smoothScroll({ $.smoothScroll({
......
...@@ -30,7 +30,7 @@ function($, _, Backbone, gettext, ...@@ -30,7 +30,7 @@ function($, _, Backbone, gettext,
'click .action-add-signatory': 'addSignatory' 'click .action-add-signatory': 'addSignatory'
}, },
className: function () { className: function() {
// Determine the CSS class names for this model instance // Determine the CSS class names for this model instance
var index = this.model.collection.indexOf(this.model); var index = this.model.collection.indexOf(this.model);
...@@ -44,12 +44,12 @@ function($, _, Backbone, gettext, ...@@ -44,12 +44,12 @@ function($, _, Backbone, gettext,
initialize: function(options) { initialize: function(options) {
// Set up the initial state of the attributes set for this model instance // Set up the initial state of the attributes set for this model instance
_.bindAll(this, "onSignatoryRemoved", "clearErrorMessage"); _.bindAll(this, 'onSignatoryRemoved', 'clearErrorMessage');
this.max_signatories_limit = options.max_signatories_limit || MAX_SIGNATORIES_LIMIT; this.max_signatories_limit = options.max_signatories_limit || MAX_SIGNATORIES_LIMIT;
this.template = _.template(certificateEditorTemplate); this.template = _.template(certificateEditorTemplate);
this.eventAgg = _.extend({}, Backbone.Events); this.eventAgg = _.extend({}, Backbone.Events);
this.eventAgg.bind("onSignatoryRemoved", this.onSignatoryRemoved); this.eventAgg.bind('onSignatoryRemoved', this.onSignatoryRemoved);
this.eventAgg.bind("onSignatoryUpdated", this.clearErrorMessage); this.eventAgg.bind('onSignatoryUpdated', this.clearErrorMessage);
ListItemEditorView.prototype.initialize.call(this); ListItemEditorView.prototype.initialize.call(this);
}, },
...@@ -69,7 +69,7 @@ function($, _, Backbone, gettext, ...@@ -69,7 +69,7 @@ function($, _, Backbone, gettext,
ListItemEditorView.prototype.render.call(this); ListItemEditorView.prototype.render.call(this);
var self = this; var self = this;
// Ensure we have at least one signatory associated with the certificate. // Ensure we have at least one signatory associated with the certificate.
this.model.get("signatories").each(function( modelSignatory) { this.model.get('signatories').each(function(modelSignatory) {
var signatory_view = new SignatoryEditorView({ var signatory_view = new SignatoryEditorView({
model: modelSignatory, model: modelSignatory,
isEditingAllCollections: true, isEditingAllCollections: true,
...@@ -89,8 +89,8 @@ function($, _, Backbone, gettext, ...@@ -89,8 +89,8 @@ function($, _, Backbone, gettext,
disableAddSignatoryButton: function() { disableAddSignatoryButton: function() {
// Disable the 'Add Signatory' link if the constraint has been met. // Disable the 'Add Signatory' link if the constraint has been met.
if(this.$(".signatory-edit-list > div.signatory-edit").length >= this.max_signatories_limit) { if (this.$('.signatory-edit-list > div.signatory-edit').length >= this.max_signatories_limit) {
this.$(".action-add-signatory").addClass("disableClick"); this.$('.action-add-signatory').addClass('disableClick');
} }
}, },
...@@ -118,7 +118,7 @@ function($, _, Backbone, gettext, ...@@ -118,7 +118,7 @@ function($, _, Backbone, gettext,
if (event && event.preventDefault) { event.preventDefault(); } if (event && event.preventDefault) { event.preventDefault(); }
this.model.set( this.model.set(
'name', this.$('.collection-name-input').val(), 'name', this.$('.collection-name-input').val(),
{ silent: true } {silent: true}
); );
}, },
...@@ -128,7 +128,7 @@ function($, _, Backbone, gettext, ...@@ -128,7 +128,7 @@ function($, _, Backbone, gettext,
this.model.set( this.model.set(
'description', 'description',
this.$('.certificate-description-input').val(), this.$('.certificate-description-input').val(),
{ silent: true } {silent: true}
); );
}, },
...@@ -138,7 +138,7 @@ function($, _, Backbone, gettext, ...@@ -138,7 +138,7 @@ function($, _, Backbone, gettext,
this.model.set( this.model.set(
'course_title', 'course_title',
this.$('.certificate-course-title-input').val(), this.$('.certificate-course-title-input').val(),
{ silent: true } {silent: true}
); );
}, },
......
...@@ -7,7 +7,7 @@ define([ ...@@ -7,7 +7,7 @@ define([
'js/certificates/views/certificate_details', 'js/certificates/views/certificate_details',
'js/certificates/views/certificate_editor' 'js/certificates/views/certificate_editor'
], ],
function (gettext, ListItemView, CertificateDetailsView, CertificateEditorView) { function(gettext, ListItemView, CertificateDetailsView, CertificateEditorView) {
'use strict'; 'use strict';
var CertificateItemView = ListItemView.extend({ var CertificateItemView = ListItemView.extend({
events: { events: {
...@@ -20,7 +20,7 @@ function (gettext, ListItemView, CertificateDetailsView, CertificateEditorView) ...@@ -20,7 +20,7 @@ function (gettext, ListItemView, CertificateDetailsView, CertificateEditorView)
// Translators: This field pertains to the custom label for a certificate. // Translators: This field pertains to the custom label for a certificate.
itemDisplayName: gettext('certificate'), itemDisplayName: gettext('certificate'),
attributes: function () { attributes: function() {
// Retrieves the defined attribute set // Retrieves the defined attribute set
return { return {
'id': this.model.get('id'), 'id': this.model.get('id'),
......
...@@ -8,25 +8,25 @@ define([ ...@@ -8,25 +8,25 @@ define([
'js/views/baseview', 'js/views/baseview',
'common/js/components/utils/view_utils', 'common/js/components/utils/view_utils',
'common/js/components/views/feedback_notification', 'common/js/components/views/feedback_notification',
"text!templates/certificate-web-preview.underscore" 'text!templates/certificate-web-preview.underscore'
], ],
function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPreviewTemplate) { function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPreviewTemplate) {
'use strict'; 'use strict';
var CertificateWebPreview = BaseView.extend({ var CertificateWebPreview = BaseView.extend({
el: $(".preview-certificate"), el: $('.preview-certificate'),
events: { events: {
"change #course-modes": "courseModeChanged", 'change #course-modes': 'courseModeChanged',
"click .activate-cert": "toggleCertificateActivation" 'click .activate-cert': 'toggleCertificateActivation'
}, },
initialize: function (options) { initialize: function(options) {
this.course_modes = options.course_modes; this.course_modes = options.course_modes;
this.certificate_web_view_url = options.certificate_web_view_url; this.certificate_web_view_url = options.certificate_web_view_url;
this.certificate_activation_handler_url = options.certificate_activation_handler_url; this.certificate_activation_handler_url = options.certificate_activation_handler_url;
this.is_active = options.is_active; this.is_active = options.is_active;
}, },
render: function () { render: function() {
this.$el.html(_.template(certificateWebPreviewTemplate)({ this.$el.html(_.template(certificateWebPreviewTemplate)({
course_modes: this.course_modes, course_modes: this.course_modes,
certificate_web_view_url: this.certificate_web_view_url, certificate_web_view_url: this.certificate_web_view_url,
...@@ -36,9 +36,9 @@ function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPrevie ...@@ -36,9 +36,9 @@ function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPrevie
}, },
toggleCertificateActivation: function() { toggleCertificateActivation: function() {
var msg = "Activating"; var msg = 'Activating';
if(this.is_active) { if (this.is_active) {
msg = "Deactivating"; msg = 'Deactivating';
} }
var notification = new NotificationView.Mini({ var notification = new NotificationView.Mini({
...@@ -47,24 +47,24 @@ function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPrevie ...@@ -47,24 +47,24 @@ function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPrevie
$.ajax({ $.ajax({
url: this.certificate_activation_handler_url, url: this.certificate_activation_handler_url,
type: "POST", type: 'POST',
dataType: "json", dataType: 'json',
contentType: "application/json", contentType: 'application/json',
data: JSON.stringify({ data: JSON.stringify({
is_active: !this.is_active is_active: !this.is_active
}), }),
beforeSend: function() { beforeSend: function() {
notification.show(); notification.show();
}, },
success: function(){ success: function() {
notification.hide(); notification.hide();
location.reload(); location.reload();
} }
}); });
}, },
courseModeChanged: function (event) { courseModeChanged: function(event) {
$('.preview-certificate-link').attr('href', function(index, value){ $('.preview-certificate-link').attr('href', function(index, value) {
return value.replace(/preview=([^&]+)/, function() { return value.replace(/preview=([^&]+)/, function() {
return 'preview=' + event.target.options[event.target.selectedIndex].text; return 'preview=' + event.target.options[event.target.selectedIndex].text;
}); });
......
...@@ -5,7 +5,7 @@ define([ ...@@ -5,7 +5,7 @@ define([
'js/views/list', 'js/views/list',
'js/certificates/views/certificate_item' 'js/certificates/views/certificate_item'
], ],
function (gettext, ListView, CertificateItemView) { function(gettext, ListView, CertificateItemView) {
'use strict'; 'use strict';
var CertificatesListView = ListView.extend({ var CertificatesListView = ListView.extend({
tagName: 'div', tagName: 'div',
......
...@@ -7,7 +7,7 @@ define([ ...@@ -7,7 +7,7 @@ define([
'js/views/pages/base_page', 'js/views/pages/base_page',
'js/certificates/views/certificates_list' 'js/certificates/views/certificates_list'
], ],
function ($, _, gettext, BasePage, CertificatesListView) { function($, _, gettext, BasePage, CertificatesListView) {
'use strict'; 'use strict';
var CertificatesPage = BasePage.extend({ var CertificatesPage = BasePage.extend({
......
...@@ -13,7 +13,7 @@ define([ ...@@ -13,7 +13,7 @@ define([
'text!templates/signatory-details.underscore', 'text!templates/signatory-details.underscore',
'text!templates/signatory-actions.underscore' 'text!templates/signatory-actions.underscore'
], ],
function ($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, SignatoryEditorView, function($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, SignatoryEditorView,
signatoryDetailsTemplate, signatoryActionsTemplate) { signatoryDetailsTemplate, signatoryActionsTemplate) {
'use strict'; 'use strict';
var SignatoryDetailsView = BaseView.extend({ var SignatoryDetailsView = BaseView.extend({
...@@ -25,7 +25,7 @@ function ($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, Sign ...@@ -25,7 +25,7 @@ function ($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, Sign
}, },
className: function () { className: function() {
// Determine the CSS class names for this model instance // Determine the CSS class names for this model instance
var index = this.model.collection.indexOf(this.model); var index = this.model.collection.indexOf(this.model);
return [ return [
...@@ -62,13 +62,13 @@ function ($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, Sign ...@@ -62,13 +62,13 @@ function ($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, Sign
// Persist the data for this model // Persist the data for this model
if (event && event.preventDefault) { event.preventDefault(); } if (event && event.preventDefault) { event.preventDefault(); }
var certificate = this.model.get('certificate'); var certificate = this.model.get('certificate');
if (!certificate.isValid()){ if (!certificate.isValid()) {
return; return;
} }
var self = this; var self = this;
ViewUtils.runOperationShowingMessage( ViewUtils.runOperationShowingMessage(
gettext('Saving'), gettext('Saving'),
function () { function() {
var dfd = $.Deferred(); var dfd = $.Deferred();
var actionableModel = certificate; var actionableModel = certificate;
actionableModel.save({}, { actionableModel.save({}, {
......
...@@ -13,7 +13,7 @@ define([ ...@@ -13,7 +13,7 @@ define([
'js/views/uploads', 'js/views/uploads',
'text!templates/signatory-editor.underscore' 'text!templates/signatory-editor.underscore'
], ],
function ($, _, Backbone, gettext, function($, _, Backbone, gettext,
TemplateUtils, ViewUtils, PromptView, NotificationView, FileUploadModel, FileUploadDialog, TemplateUtils, ViewUtils, PromptView, NotificationView, FileUploadModel, FileUploadDialog,
signatoryEditorTemplate) { signatoryEditorTemplate) {
'use strict'; 'use strict';
...@@ -28,7 +28,7 @@ function ($, _, Backbone, gettext, ...@@ -28,7 +28,7 @@ function ($, _, Backbone, gettext,
'click .action-upload-signature': 'uploadSignatureImage' 'click .action-upload-signature': 'uploadSignatureImage'
}, },
className: function () { className: function() {
// Determine the CSS class names for this model instance // Determine the CSS class names for this model instance
var index = this.getModelIndex(this.model); var index = this.getModelIndex(this.model);
return [ return [
...@@ -39,7 +39,7 @@ function ($, _, Backbone, gettext, ...@@ -39,7 +39,7 @@ function ($, _, Backbone, gettext,
initialize: function(options) { initialize: function(options) {
// Set up the initial state of the attributes set for this model instance // Set up the initial state of the attributes set for this model instance
_.bindAll(this, 'render'); _.bindAll(this, 'render');
this.model.bind('change', this.render); this.model.bind('change', this.render);
this.eventAgg = options.eventAgg; this.eventAgg = options.eventAgg;
this.isEditingAllCollections = options.isEditingAllCollections; this.isEditingAllCollections = options.isEditingAllCollections;
...@@ -58,8 +58,8 @@ function ($, _, Backbone, gettext, ...@@ -58,8 +58,8 @@ function ($, _, Backbone, gettext,
getTotalSignatoriesOnServer: function() { getTotalSignatoriesOnServer: function() {
// Retrieve the count of signatories stored server-side // Retrieve the count of signatories stored server-side
var count = 0; var count = 0;
this.model.collection.each(function( modelSignatory) { this.model.collection.each(function(modelSignatory) {
if(!modelSignatory.isNew()) { if (!modelSignatory.isNew()) {
count ++; count ++;
} }
}); });
...@@ -87,10 +87,10 @@ function ($, _, Backbone, gettext, ...@@ -87,10 +87,10 @@ function ($, _, Backbone, gettext,
this.model.set( this.model.set(
'name', 'name',
this.$('.signatory-name-input').val(), this.$('.signatory-name-input').val(),
{ silent: true } {silent: true}
); );
this.toggleValidationErrorMessage('name'); this.toggleValidationErrorMessage('name');
this.eventAgg.trigger("onSignatoryUpdated", this.model); this.eventAgg.trigger('onSignatoryUpdated', this.model);
}, },
setSignatoryTitle: function(event) { setSignatoryTitle: function(event) {
...@@ -99,10 +99,10 @@ function ($, _, Backbone, gettext, ...@@ -99,10 +99,10 @@ function ($, _, Backbone, gettext,
this.model.set( this.model.set(
'title', 'title',
this.$('.signatory-title-input').val(), this.$('.signatory-title-input').val(),
{ silent:true } {silent: true}
); );
this.toggleValidationErrorMessage('title'); this.toggleValidationErrorMessage('title');
this.eventAgg.trigger("onSignatoryUpdated", this.model); this.eventAgg.trigger('onSignatoryUpdated', this.model);
}, },
setSignatoryOrganization: function(event) { setSignatoryOrganization: function(event) {
...@@ -111,9 +111,9 @@ function ($, _, Backbone, gettext, ...@@ -111,9 +111,9 @@ function ($, _, Backbone, gettext,
this.model.set( this.model.set(
'organization', 'organization',
this.$('.signatory-organization-input').val(), this.$('.signatory-organization-input').val(),
{ silent: true } {silent: true}
); );
this.eventAgg.trigger("onSignatoryUpdated", this.model); this.eventAgg.trigger('onSignatoryUpdated', this.model);
}, },
setSignatorySignatureImagePath: function(event) { setSignatorySignatureImagePath: function(event) {
...@@ -121,7 +121,7 @@ function ($, _, Backbone, gettext, ...@@ -121,7 +121,7 @@ function ($, _, Backbone, gettext,
this.model.set( this.model.set(
'signature_image_path', 'signature_image_path',
this.$('.signatory-signature-input').val(), this.$('.signatory-signature-input').val(),
{ silent: true } {silent: true}
); );
}, },
...@@ -137,21 +137,21 @@ function ($, _, Backbone, gettext, ...@@ -137,21 +137,21 @@ function ($, _, Backbone, gettext,
actions: { actions: {
primary: { primary: {
text: gettext('Delete'), text: gettext('Delete'),
click: function () { click: function() {
var deleting = new NotificationView.Mini({ var deleting = new NotificationView.Mini({
title: gettext('Deleting') title: gettext('Deleting')
}); });
if (model.isNew()){ if (model.isNew()) {
model.collection.remove(model); model.collection.remove(model);
self.eventAgg.trigger("onSignatoryRemoved", model); self.eventAgg.trigger('onSignatoryRemoved', model);
} }
else { else {
deleting.show(); deleting.show();
model.destroy({ model.destroy({
wait: true, wait: true,
success: function (model) { success: function(model) {
deleting.hide(); deleting.hide();
self.eventAgg.trigger("onSignatoryRemoved", model); self.eventAgg.trigger('onSignatoryRemoved', model);
} }
}); });
} }
...@@ -172,8 +172,8 @@ function ($, _, Backbone, gettext, ...@@ -172,8 +172,8 @@ function ($, _, Backbone, gettext,
uploadSignatureImage: function(event) { uploadSignatureImage: function(event) {
event.preventDefault(); event.preventDefault();
var upload = new FileUploadModel({ var upload = new FileUploadModel({
title: gettext("Upload signature image."), title: gettext('Upload signature image.'),
message: gettext("Image must be in PNG format."), message: gettext('Image must be in PNG format.'),
mimeTypes: ['image/png'] mimeTypes: ['image/png']
}); });
var self = this; var self = this;
...@@ -192,20 +192,19 @@ function ($, _, Backbone, gettext, ...@@ -192,20 +192,19 @@ function ($, _, Backbone, gettext,
* @param string modelAttribute - the attribute of the signatory model e.g. name, title. * @param string modelAttribute - the attribute of the signatory model e.g. name, title.
*/ */
toggleValidationErrorMessage: function(modelAttribute) { toggleValidationErrorMessage: function(modelAttribute) {
var selector = "div.add-signatory-" + modelAttribute; var selector = 'div.add-signatory-' + modelAttribute;
if (!this.model.isValid() && _.has(this.model.validationError, modelAttribute)) { if (!this.model.isValid() && _.has(this.model.validationError, modelAttribute)) {
// Show the error message if it is not exist before. // Show the error message if it is not exist before.
if( !$(selector).hasClass('error')) { if (!$(selector).hasClass('error')) {
var errorMessage = this.model.validationError[modelAttribute]; var errorMessage = this.model.validationError[modelAttribute];
$(selector).addClass("error"); $(selector).addClass('error');
$(selector).append("<span class='message-error'>" + errorMessage + "</span>"); $(selector).append("<span class='message-error'>" + errorMessage + '</span>');
} }
} }
else { else {
// Remove the error message. // Remove the error message.
$(selector).removeClass("error"); $(selector).removeClass('error');
$(selector + ">span.message-error").remove(); $(selector + '>span.message-error').remove();
} }
} }
......
define([ define([
"underscore", 'underscore',
"edx-ui-toolkit/js/pagination/paging-collection", 'edx-ui-toolkit/js/pagination/paging-collection',
"js/models/asset" 'js/models/asset'
], function(_, PagingCollection, AssetModel) { ], function(_, PagingCollection, AssetModel) {
'use strict'; 'use strict';
var AssetCollection = PagingCollection.extend({ var AssetCollection = PagingCollection.extend({
assetType: '', assetType: '',
model : AssetModel, model: AssetModel,
state: { state: {
firstPage: 0, firstPage: 0,
......
define(["backbone", "js/models/chapter"], function(Backbone, ChapterModel) { define(['backbone', 'js/models/chapter'], function(Backbone, ChapterModel) {
var ChapterCollection = Backbone.Collection.extend({ var ChapterCollection = Backbone.Collection.extend({
model: ChapterModel, model: ChapterModel,
comparator: "order", comparator: 'order',
nextOrder: function() { nextOrder: function() {
if(!this.length) return 1; if (!this.length) return 1;
return this.last().get('order') + 1; return this.last().get('order') + 1;
}, },
isEmpty: function() { isEmpty: function() {
......
define(["backbone", "js/models/component_template"], function(Backbone, ComponentTemplate) { define(['backbone', 'js/models/component_template'], function(Backbone, ComponentTemplate) {
return Backbone.Collection.extend({ return Backbone.Collection.extend({
model : ComponentTemplate model: ComponentTemplate
}); });
}); });
define(["backbone", "js/models/settings/course_grader"], function(Backbone, CourseGrader) { define(['backbone', 'js/models/settings/course_grader'], function(Backbone, CourseGrader) {
var CourseGraderCollection = Backbone.Collection.extend({
model: CourseGrader,
sumWeights: function() {
return this.reduce(function(subtotal, grader) { return subtotal + grader.get('weight'); }, 0);
}
});
var CourseGraderCollection = Backbone.Collection.extend({ return CourseGraderCollection;
model : CourseGrader,
sumWeights : function() {
return this.reduce(function(subtotal, grader) { return subtotal + grader.get('weight'); }, 0);
}
});
return CourseGraderCollection;
}); // end define() }); // end define()
define(["backbone", "js/models/course_update"], function(Backbone, CourseUpdateModel) { define(['backbone', 'js/models/course_update'], function(Backbone, CourseUpdateModel) {
/* /*
The intitializer of this collection must set id to the update's location.url and courseLocation to the course's location. Must pass the The intitializer of this collection must set id to the update's location.url and courseLocation to the course's location. Must pass the
collection of updates as [{ date : "month day", content : "html"}] collection of updates as [{ date : "month day", content : "html"}]
...@@ -6,7 +6,7 @@ define(["backbone", "js/models/course_update"], function(Backbone, CourseUpdateM ...@@ -6,7 +6,7 @@ define(["backbone", "js/models/course_update"], function(Backbone, CourseUpdateM
var CourseUpdateCollection = Backbone.Collection.extend({ var CourseUpdateCollection = Backbone.Collection.extend({
// instantiator must set url // instantiator must set url
model : CourseUpdateModel model: CourseUpdateModel
}); });
return CourseUpdateCollection; return CourseUpdateCollection;
}); });
define([ define([
'underscore', 'underscore.string', 'backbone', 'gettext', 'js/models/group' 'underscore', 'underscore.string', 'backbone', 'gettext', 'js/models/group'
], ],
function (_, str, Backbone, gettext, GroupModel) { function(_, str, Backbone, gettext, GroupModel) {
'use strict'; 'use strict';
var GroupCollection = Backbone.Collection.extend({ var GroupCollection = Backbone.Collection.extend({
model: GroupModel, model: GroupModel,
...@@ -11,7 +11,7 @@ function (_, str, Backbone, gettext, GroupModel) { ...@@ -11,7 +11,7 @@ function (_, str, Backbone, gettext, GroupModel) {
* @return {Number} * @return {Number}
*/ */
nextOrder: function() { nextOrder: function() {
if(!this.length) { if (!this.length) {
return 0; return 0;
} }
...@@ -33,7 +33,7 @@ function (_, str, Backbone, gettext, GroupModel) { ...@@ -33,7 +33,7 @@ function (_, str, Backbone, gettext, GroupModel) {
* @examples * @examples
* Group A, Group B, Group AA, Group ZZZ etc. * Group A, Group B, Group AA, Group ZZZ etc.
*/ */
getNextDefaultGroupName: function () { getNextDefaultGroupName: function() {
var index = this.nextOrder(), var index = this.nextOrder(),
usedNames = _.pluck(this.toJSON(), 'name'), usedNames = _.pluck(this.toJSON(), 'name'),
name = ''; name = '';
...@@ -53,7 +53,7 @@ function (_, str, Backbone, gettext, GroupModel) { ...@@ -53,7 +53,7 @@ function (_, str, Backbone, gettext, GroupModel) {
* @examples * @examples
* A, B, AA in Group A, Group B, ..., Group AA, etc. * A, B, AA in Group A, Group B, ..., Group AA, etc.
*/ */
getGroupId: (function () { getGroupId: (function() {
/* /*
Translators: Dictionary used for creation ids that are used in Translators: Dictionary used for creation ids that are used in
default group names. For example: A, B, AA in Group A, default group names. For example: A, B, AA in Group A,
......
define(["backbone", "js/models/metadata"], function(Backbone, MetadataModel) { define(['backbone', 'js/models/metadata'], function(Backbone, MetadataModel) {
var MetadataCollection = Backbone.Collection.extend({ var MetadataCollection = Backbone.Collection.extend({
model : MetadataModel, model: MetadataModel,
comparator: "display_name" comparator: 'display_name'
}); });
return MetadataCollection; return MetadataCollection;
}); });
define(["backbone", "js/models/textbook"], define(['backbone', 'js/models/textbook'],
function(Backbone, TextbookModel) { function(Backbone, TextbookModel) {
var TextbookCollection = Backbone.Collection.extend({ var TextbookCollection = Backbone.Collection.extend({
model: TextbookModel, model: TextbookModel,
url: function() { return CMS.URL.TEXTBOOKS; } url: function() { return CMS.URL.TEXTBOOKS; }
}); });
return TextbookCollection; return TextbookCollection;
}); });
...@@ -2,17 +2,17 @@ define([ ...@@ -2,17 +2,17 @@ define([
'jquery', 'js/collections/asset', 'js/views/assets', 'jquery.fileupload' 'jquery', 'js/collections/asset', 'js/views/assets', 'jquery.fileupload'
], function($, AssetCollection, AssetsView) { ], function($, AssetCollection, AssetsView) {
'use strict'; 'use strict';
return function (config) { return function(config) {
var assets = new AssetCollection(), var assets = new AssetCollection(),
assetsView; assetsView;
assets.url = config.assetCallbackUrl; assets.url = config.assetCallbackUrl;
assetsView = new AssetsView({ assetsView = new AssetsView({
collection: assets, collection: assets,
el: $('.wrapper-assets'), el: $('.wrapper-assets'),
uploadChunkSizeInMBs: config.uploadChunkSizeInMBs, uploadChunkSizeInMBs: config.uploadChunkSizeInMBs,
maxFileSizeInMBs: config.maxFileSizeInMBs, maxFileSizeInMBs: config.maxFileSizeInMBs,
maxFileSizeRedirectUrl: config.maxFileSizeRedirectUrl maxFileSizeRedirectUrl: config.maxFileSizeRedirectUrl
}); });
assetsView.render(); assetsView.render();
}; };
......
...@@ -5,7 +5,7 @@ define([ ...@@ -5,7 +5,7 @@ define([
], ],
function($, _, XBlockContainerInfo, ContainerPage, ComponentTemplates, xmoduleLoader) { function($, _, XBlockContainerInfo, ContainerPage, ComponentTemplates, xmoduleLoader) {
'use strict'; 'use strict';
return function (componentTemplates, XBlockInfoJson, action, options) { return function(componentTemplates, XBlockInfoJson, action, options) {
var main_options = { var main_options = {
el: $('#content'), el: $('#content'),
model: new XBlockContainerInfo(XBlockInfoJson, {parse: true}), model: new XBlockContainerInfo(XBlockInfoJson, {parse: true}),
...@@ -13,7 +13,7 @@ function($, _, XBlockContainerInfo, ContainerPage, ComponentTemplates, xmoduleLo ...@@ -13,7 +13,7 @@ function($, _, XBlockContainerInfo, ContainerPage, ComponentTemplates, xmoduleLo
templates: new ComponentTemplates(componentTemplates, {parse: true}) templates: new ComponentTemplates(componentTemplates, {parse: true})
}; };
xmoduleLoader.done(function () { xmoduleLoader.done(function() {
var view = new ContainerPage(_.extend(main_options, options)); var view = new ContainerPage(_.extend(main_options, options));
view.render(); view.render();
}); });
......
define(['jquery', 'jquery.form', 'js/views/course_rerun'], function ($) { define(['jquery', 'jquery.form', 'js/views/course_rerun'], function($) {
'use strict'; 'use strict';
return function () {}; return function() {};
}); });
...@@ -3,7 +3,7 @@ define([ ...@@ -3,7 +3,7 @@ define([
'js/models/course_info', 'js/views/course_info_edit' 'js/models/course_info', 'js/views/course_info_edit'
], function($, CourseUpdateCollection, ModuleInfoModel, CourseInfoModel, CourseInfoEditView) { ], function($, CourseUpdateCollection, ModuleInfoModel, CourseInfoModel, CourseInfoEditView) {
'use strict'; 'use strict';
return function (updatesUrl, handoutsLocator, baseAssetUrl, push_notification_enabled) { return function(updatesUrl, handoutsLocator, baseAssetUrl, push_notification_enabled) {
var course_updates = new CourseUpdateCollection(), var course_updates = new CourseUpdateCollection(),
course_handouts, editor; course_handouts, editor;
...@@ -14,10 +14,10 @@ define([ ...@@ -14,10 +14,10 @@ define([
}); });
editor = new CourseInfoEditView({ editor = new CourseInfoEditView({
el: $('.main-wrapper'), el: $('.main-wrapper'),
model : new CourseInfoModel({ model: new CourseInfoModel({
updates : course_updates, updates: course_updates,
base_asset_url : baseAssetUrl, base_asset_url: baseAssetUrl,
handouts : course_handouts handouts: course_handouts
}), }),
push_notification_enabled: push_notification_enabled push_notification_enabled: push_notification_enabled
}); });
......
define([ define([
'js/models/explicit_url', 'js/views/tabs', 'xmodule', 'cms/js/main', 'xblock/cms.runtime.v1' 'js/models/explicit_url', 'js/views/tabs', 'xmodule', 'cms/js/main', 'xblock/cms.runtime.v1'
], function (TabsModel, TabsEditView, xmoduleLoader) { ], function(TabsModel, TabsEditView, xmoduleLoader) {
'use strict'; 'use strict';
return function (courseLocation, explicitUrl) { return function(courseLocation, explicitUrl) {
xmoduleLoader.done(function () { xmoduleLoader.done(function() {
var model = new TabsModel({ var model = new TabsModel({
id: courseLocation, id: courseLocation,
explicit_url: explicitUrl explicit_url: explicitUrl
......
define(['gettext', 'common/js/components/views/feedback_prompt'], function(gettext, PromptView) { define(['gettext', 'common/js/components/views/feedback_prompt'], function(gettext, PromptView) {
'use strict'; 'use strict';
return function (hasUnit, editUnitUrl, courselikeHomeUrl, library, errMsg) { return function(hasUnit, editUnitUrl, courselikeHomeUrl, library, errMsg) {
var dialog; var dialog;
if(hasUnit) { if (hasUnit) {
dialog = new PromptView({ dialog = new PromptView({
title: gettext('There has been an error while exporting.'), title: gettext('There has been an error while exporting.'),
message: gettext('There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages.'), message: gettext('There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages.'),
...@@ -28,10 +28,10 @@ define(['gettext', 'common/js/components/views/feedback_prompt'], function(gette ...@@ -28,10 +28,10 @@ define(['gettext', 'common/js/components/views/feedback_prompt'], function(gette
var action; var action;
if (library) { if (library) {
msg += gettext('Your library could not be exported to XML. There is not enough information to identify the failed component. Inspect your library to identify any problematic components and try again.'); msg += gettext('Your library could not be exported to XML. There is not enough information to identify the failed component. Inspect your library to identify any problematic components and try again.');
action = gettext('Take me to the main library page') action = gettext('Take me to the main library page');
} else { } else {
msg += gettext('Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again.'); msg += gettext('Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again.');
action = gettext('Take me to the main course page') action = gettext('Take me to the main course page');
} }
msg += '</p><p>' + gettext('The raw error message is:') + '</p>' + errMsg; msg += '</p><p>' + gettext('The raw error message is:') + '</p>' + errMsg;
dialog = new PromptView({ dialog = new PromptView({
...@@ -49,7 +49,7 @@ define(['gettext', 'common/js/components/views/feedback_prompt'], function(gette ...@@ -49,7 +49,7 @@ define(['gettext', 'common/js/components/views/feedback_prompt'], function(gette
secondary: { secondary: {
text: gettext('Cancel'), text: gettext('Cancel'),
click: function(view) { click: function(view) {
view.hide(); view.hide();
} }
} }
} }
......
...@@ -2,7 +2,7 @@ define([ ...@@ -2,7 +2,7 @@ define([
'js/collections/group_configuration', 'js/models/group_configuration', 'js/views/pages/group_configurations' 'js/collections/group_configuration', 'js/models/group_configuration', 'js/views/pages/group_configurations'
], function(GroupConfigurationCollection, GroupConfigurationModel, GroupConfigurationsPage) { ], function(GroupConfigurationCollection, GroupConfigurationModel, GroupConfigurationsPage) {
'use strict'; 'use strict';
return function (experimentsEnabled, experimentGroupConfigurationsJson, contentGroupConfigurationJson, return function(experimentsEnabled, experimentGroupConfigurationsJson, contentGroupConfigurationJson,
groupConfigurationUrl, courseOutlineUrl) { groupConfigurationUrl, courseOutlineUrl) {
var experimentGroupConfigurations = new GroupConfigurationCollection( var experimentGroupConfigurations = new GroupConfigurationCollection(
experimentGroupConfigurationsJson, {parse: true} experimentGroupConfigurationsJson, {parse: true}
......
define([ define([
'domReady', 'js/views/import', 'jquery', 'gettext', 'jquery.fileupload', 'jquery.cookie' 'domReady', 'js/views/import', 'jquery', 'gettext', 'jquery.fileupload', 'jquery.cookie'
], function(domReady, Import, $, gettext) { ], function(domReady, Import, $, gettext) {
'use strict'; 'use strict';
return function (feedbackUrl, library) { return function(feedbackUrl, library) {
var dbError; var dbError;
if (library) { if (library) {
...@@ -27,14 +26,14 @@ define([ ...@@ -27,14 +26,14 @@ define([
previousImport = Import.storedImport(), previousImport = Import.storedImport(),
file; file;
var onComplete = function () { var onComplete = function() {
bar.hide(); bar.hide();
chooseBtn chooseBtn
.find('.copy').html(gettext("Choose new file")).end() .find('.copy').html(gettext('Choose new file')).end()
.show(); .show();
} };
$(window).on('beforeunload', function (event) { unloading = true; }); $(window).on('beforeunload', function(event) { unloading = true; });
// Display the status of last file upload on page load // Display the status of last file upload on page load
if (previousImport) { if (previousImport) {
...@@ -70,11 +69,11 @@ define([ ...@@ -70,11 +69,11 @@ define([
).then(onComplete); ).then(onComplete);
submitBtn.hide(); submitBtn.hide();
data.submit().complete(function (result, textStatus, xhr) { data.submit().complete(function(result, textStatus, xhr) {
if (xhr.status !== 200) { if (xhr.status !== 200) {
var serverMsg, errMsg, stage; var serverMsg, errMsg, stage;
try{ try {
serverMsg = $.parseJSON(result.responseText) || {}; serverMsg = $.parseJSON(result.responseText) || {};
} catch (e) { } catch (e) {
return; return;
...@@ -104,7 +103,7 @@ define([ ...@@ -104,7 +103,7 @@ define([
} }
}, },
progressall: function(e, data){ progressall: function(e, data) {
var percentInt = data.loaded / data.total * 100, var percentInt = data.loaded / data.total * 100,
percentVal = parseInt(percentInt, 10) + '%', percentVal = parseInt(percentInt, 10) + '%',
doneAt; doneAt;
...@@ -121,7 +120,7 @@ define([ ...@@ -121,7 +120,7 @@ define([
// Start feedback with delay so that current stage of // Start feedback with delay so that current stage of
// import properly updates in session // import properly updates in session
setTimeout(function () { Import.pollStatus(); }, 3000); setTimeout(function() { Import.pollStatus(); }, 3000);
} else { } else {
bar.show(); bar.show();
fill.width(percentVal).html(percentVal); fill.width(percentVal).html(percentVal);
...@@ -132,7 +131,7 @@ define([ ...@@ -132,7 +131,7 @@ define([
}); });
var showImportSubmit = function (e) { var showImportSubmit = function(e) {
var filepath = $(this).val(); var filepath = $(this).val();
if (filepath.substr(filepath.length - 6, 6) === 'tar.gz') { if (filepath.substr(filepath.length - 6, 6) === 'tar.gz') {
...@@ -150,10 +149,10 @@ define([ ...@@ -150,10 +149,10 @@ define([
} }
}; };
domReady(function () { domReady(function() {
// import form setup // import form setup
$('.view-import .file-input').bind('change', showImportSubmit); $('.view-import .file-input').bind('change', showImportSubmit);
$('.view-import .choose-file-button, .view-import .choose-file-button-inline').bind('click', function (e) { $('.view-import .choose-file-button, .view-import .choose-file-button-inline').bind('click', function(e) {
e.preventDefault(); e.preventDefault();
$('.view-import .file-input').click(); $('.view-import .file-input').click();
}); });
......
define(['jquery.form', 'js/index'], function() { define(['jquery.form', 'js/index'], function() {
'use strict'; 'use strict';
return function () { return function() {
// showing/hiding creation rights UI // showing/hiding creation rights UI
$('.show-creationrights').click(function(e) { $('.show-creationrights').click(function(e) {
e.preventDefault(); e.preventDefault();
...@@ -11,11 +11,11 @@ define(['jquery.form', 'js/index'], function() { ...@@ -11,11 +11,11 @@ define(['jquery.form', 'js/index'], function() {
.toggleClass('current'); .toggleClass('current');
}); });
var reloadPage = function () { var reloadPage = function() {
location.reload(); location.reload();
}; };
var showError = function () { var showError = function() {
$('#request-coursecreator-submit') $('#request-coursecreator-submit')
.toggleClass('has-error') .toggleClass('has-error')
.find('.label') .find('.label')
...@@ -30,7 +30,7 @@ define(['jquery.form', 'js/index'], function() { ...@@ -30,7 +30,7 @@ define(['jquery.form', 'js/index'], function() {
success: reloadPage success: reloadPage
}); });
$('#request-coursecreator-submit').click(function(event){ $('#request-coursecreator-submit').click(function(event) {
$(this) $(this)
.toggleClass('is-disabled is-submitting') .toggleClass('is-disabled is-submitting')
.attr('aria-disabled', $(this).hasClass('is-disabled')) .attr('aria-disabled', $(this).hasClass('is-disabled'))
......
...@@ -5,7 +5,7 @@ define([ ...@@ -5,7 +5,7 @@ define([
], ],
function($, _, XBlockInfo, PagedContainerPage, LibraryContainerView, ComponentTemplates, xmoduleLoader) { function($, _, XBlockInfo, PagedContainerPage, LibraryContainerView, ComponentTemplates, xmoduleLoader) {
'use strict'; 'use strict';
return function (componentTemplates, XBlockInfoJson, options) { return function(componentTemplates, XBlockInfoJson, options) {
var main_options = { var main_options = {
el: $('#content'), el: $('#content'),
model: new XBlockInfo(XBlockInfoJson, {parse: true}), model: new XBlockInfo(XBlockInfoJson, {parse: true}),
...@@ -15,7 +15,7 @@ function($, _, XBlockInfo, PagedContainerPage, LibraryContainerView, ComponentTe ...@@ -15,7 +15,7 @@ function($, _, XBlockInfo, PagedContainerPage, LibraryContainerView, ComponentTe
canEdit: true canEdit: true
}; };
xmoduleLoader.done(function () { xmoduleLoader.done(function() {
var view = new PagedContainerPage(_.extend(main_options, options)); var view = new PagedContainerPage(_.extend(main_options, options));
view.render(); view.render();
}); });
......
define(['jquery.cookie', 'utility', 'common/js/components/utils/view_utils'], function(cookie, utility, ViewUtils) { define(['jquery.cookie', 'utility', 'common/js/components/utils/view_utils'], function(cookie, utility, ViewUtils) {
'use strict'; 'use strict';
return function (homepageURL) { return function(homepageURL) {
function postJSON(url, data, callback) { function postJSON(url, data, callback) {
$.ajax({ $.ajax({
type:'POST', type: 'POST',
url: url, url: url,
dataType: 'json', dataType: 'json',
data: data, data: data,
success: callback, success: callback
}); });
} }
// Clear the login error message when credentials are edited // Clear the login error message when credentials are edited
$('input#email').on('input',function() { $('input#email').on('input', function() {
$('#login_error').removeClass('is-shown'); $('#login_error').removeClass('is-shown');
}); });
$('input#password').on('input',function() { $('input#password').on('input', function() {
$('#login_error').removeClass('is-shown'); $('#login_error').removeClass('is-shown');
}); });
...@@ -29,14 +29,14 @@ define(['jquery.cookie', 'utility', 'common/js/components/utils/view_utils'], fu ...@@ -29,14 +29,14 @@ define(['jquery.cookie', 'utility', 'common/js/components/utils/view_utils'], fu
var submit_data = $('#login_form').serialize(); var submit_data = $('#login_form').serialize();
postJSON('/login_post', submit_data, function(json) { postJSON('/login_post', submit_data, function(json) {
if(json.success) { if (json.success) {
var next = /next=([^&]*)/g.exec(decodeURIComponent(window.location.search)); var next = /next=([^&]*)/g.exec(decodeURIComponent(window.location.search));
if (next && next.length > 1 && !isExternal(next[1])) { if (next && next.length > 1 && !isExternal(next[1])) {
ViewUtils.redirect(next[1]); ViewUtils.redirect(next[1]);
} else { } else {
ViewUtils.redirect(homepageURL); ViewUtils.redirect(homepageURL);
} }
} else if($('#login_error').length === 0) { } else if ($('#login_error').length === 0) {
$('#login_form').prepend( $('#login_form').prepend(
'<div id="login_error" class="message message-status error">' + '<div id="login_error" class="message message-status error">' +
json.value + json.value +
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
define(['underscore', 'gettext', 'js/views/manage_users_and_roles'], define(['underscore', 'gettext', 'js/views/manage_users_and_roles'],
function(_, gettext, ManageUsersAndRoles) { function(_, gettext, ManageUsersAndRoles) {
'use strict'; 'use strict';
return function (containerName, users, tplUserURL, current_user_id, allow_actions) { return function(containerName, users, tplUserURL, current_user_id, allow_actions) {
function updateMessages(messages) { function updateMessages(messages) {
var local_messages = _.extend({}, messages); var local_messages = _.extend({}, messages);
local_messages.alreadyMember.title = gettext('Already a course team member'); local_messages.alreadyMember.title = gettext('Already a course team member');
...@@ -16,10 +16,10 @@ function(_, gettext, ManageUsersAndRoles) { ...@@ -16,10 +16,10 @@ function(_, gettext, ManageUsersAndRoles) {
// Roles order are important: first role is considered initial role (the role added to user when (s)he's added // Roles order are important: first role is considered initial role (the role added to user when (s)he's added
// Last role is considered an admin role (unrestricted access + ability to manage other users' permissions) // Last role is considered an admin role (unrestricted access + ability to manage other users' permissions)
// Changing roles is performed in promote-demote fashion, so moves only to adjacent roles is allowed // Changing roles is performed in promote-demote fashion, so moves only to adjacent roles is allowed
var roles = [{key:'staff', name:gettext('Staff')}, {key:'instructor', 'name': gettext("Admin")}]; var roles = [{key: 'staff', name: gettext('Staff')}, {key: 'instructor', 'name': gettext('Admin')}];
var options = { var options = {
el: $("#content"), el: $('#content'),
containerName: containerName, containerName: containerName,
tplUserURL: tplUserURL, tplUserURL: tplUserURL,
roles: roles, roles: roles,
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
define(['underscore', 'gettext', 'js/views/manage_users_and_roles'], define(['underscore', 'gettext', 'js/views/manage_users_and_roles'],
function(_, gettext, ManageUsersAndRoles) { function(_, gettext, ManageUsersAndRoles) {
'use strict'; 'use strict';
return function (containerName, users, tplUserURL, current_user_id, allow_actions) { return function(containerName, users, tplUserURL, current_user_id, allow_actions) {
function updateMessages(messages) { function updateMessages(messages) {
var local_messages = _.extend({}, messages); var local_messages = _.extend({}, messages);
local_messages.alreadyMember.title = gettext('Already a library team member'); local_messages.alreadyMember.title = gettext('Already a library team member');
...@@ -17,13 +17,13 @@ function(_, gettext, ManageUsersAndRoles) { ...@@ -17,13 +17,13 @@ function(_, gettext, ManageUsersAndRoles) {
// Last role is considered an admin role (unrestricted access + ability to manage other users' permissions) // Last role is considered an admin role (unrestricted access + ability to manage other users' permissions)
// Changing roles is performed in promote-demote fashion, so moves only to adjacent roles is allowed // Changing roles is performed in promote-demote fashion, so moves only to adjacent roles is allowed
var roles = [ var roles = [
{key:'library_user', name:gettext('Library User')}, {key: 'library_user', name: gettext('Library User')},
{key:'staff', name:gettext('Staff')}, {key: 'staff', name: gettext('Staff')},
{key:'instructor', 'name': gettext("Admin")} {key: 'instructor', 'name': gettext('Admin')}
]; ];
var options = { var options = {
el: $("#content"), el: $('#content'),
containerName: containerName, containerName: containerName,
tplUserURL: tplUserURL, tplUserURL: tplUserURL,
roles: roles, roles: roles,
......
...@@ -2,7 +2,7 @@ define([ ...@@ -2,7 +2,7 @@ define([
'js/views/pages/course_outline', 'js/models/xblock_outline_info' 'js/views/pages/course_outline', 'js/models/xblock_outline_info'
], function(CourseOutlinePage, XBlockOutlineInfo) { ], function(CourseOutlinePage, XBlockOutlineInfo) {
'use strict'; 'use strict';
return function (XBlockOutlineInfoJson, initialStateJson) { return function(XBlockOutlineInfoJson, initialStateJson) {
var courseXBlock = new XBlockOutlineInfo(XBlockOutlineInfoJson, {parse: true}), var courseXBlock = new XBlockOutlineInfo(XBlockOutlineInfoJson, {parse: true}),
view = new CourseOutlinePage({ view = new CourseOutlinePage({
el: $('#content'), el: $('#content'),
......
define(['jquery', 'jquery.cookie'], function($) { define(['jquery', 'jquery.cookie'], function($) {
'use strict'; 'use strict';
return function () { return function() {
$('form :input') $('form :input')
.focus(function() { .focus(function() {
$('label[for="' + this.id + '"]').addClass('is-focused'); $('label[for="' + this.id + '"]').addClass('is-focused');
...@@ -21,11 +21,11 @@ define(['jquery', 'jquery.cookie'], function($) { ...@@ -21,11 +21,11 @@ define(['jquery', 'jquery.cookie'], function($) {
notifyOnError: false, notifyOnError: false,
data: submit_data, data: submit_data,
success: function(json) { success: function(json) {
location.href = '/course/'; location.href = '/course/';
}, },
error: function(jqXHR, textStatus, errorThrown) { error: function(jqXHR, textStatus, errorThrown) {
var json = $.parseJSON(jqXHR.responseText); var json = $.parseJSON(jqXHR.responseText);
$('#register_error').html(json.value).stop().addClass('is-shown'); $('#register_error').html(json.value).stop().addClass('is-shown');
} }
}); });
}); });
......
...@@ -2,7 +2,7 @@ define([ ...@@ -2,7 +2,7 @@ define([
'jquery', 'js/models/settings/course_details', 'js/views/settings/main' 'jquery', 'js/models/settings/course_details', 'js/views/settings/main'
], function($, CourseDetailsModel, MainView) { ], function($, CourseDetailsModel, MainView) {
'use strict'; 'use strict';
return function (detailsUrl, showMinGradeWarning) { return function(detailsUrl, showMinGradeWarning) {
var model; var model;
// highlighting labels when fields are focused in // highlighting labels when fields are focused in
$('form :input') $('form :input')
......
...@@ -2,7 +2,7 @@ define([ ...@@ -2,7 +2,7 @@ define([
'jquery', 'gettext', 'js/models/settings/advanced', 'js/views/settings/advanced' 'jquery', 'gettext', 'js/models/settings/advanced', 'js/views/settings/advanced'
], function($, gettext, AdvancedSettingsModel, AdvancedSettingsView) { ], function($, gettext, AdvancedSettingsModel, AdvancedSettingsView) {
'use strict'; 'use strict';
return function (advancedDict, advancedSettingsUrl) { return function(advancedDict, advancedSettingsUrl) {
var advancedModel, editor; var advancedModel, editor;
$('form :input') $('form :input')
......
...@@ -2,7 +2,7 @@ define([ ...@@ -2,7 +2,7 @@ define([
'jquery', 'js/views/settings/grading', 'js/models/settings/course_grading_policy' 'jquery', 'js/views/settings/grading', 'js/models/settings/course_grading_policy'
], function($, GradingView, CourseGradingPolicyModel) { ], function($, GradingView, CourseGradingPolicyModel) {
'use strict'; 'use strict';
return function (courseDetails, gradingUrl) { return function(courseDetails, gradingUrl) {
var model, editor; var model, editor;
$('form :input') $('form :input')
...@@ -13,11 +13,11 @@ define([ ...@@ -13,11 +13,11 @@ define([
$('label').removeClass('is-focused'); $('label').removeClass('is-focused');
}); });
model = new CourseGradingPolicyModel(courseDetails,{parse:true}); model = new CourseGradingPolicyModel(courseDetails, {parse: true});
model.urlRoot = gradingUrl; model.urlRoot = gradingUrl;
editor = new GradingView({ editor = new GradingView({
el: $('.settings-grading'), el: $('.settings-grading'),
model : model model: model
}); });
editor.render(); editor.render();
}; };
......
...@@ -2,7 +2,7 @@ define([ ...@@ -2,7 +2,7 @@ define([
'gettext', 'js/models/section', 'js/collections/textbook', 'js/views/list_textbooks' 'gettext', 'js/models/section', 'js/collections/textbook', 'js/views/list_textbooks'
], function(gettext, Section, TextbookCollection, ListTextbooksView) { ], function(gettext, Section, TextbookCollection, ListTextbooksView) {
'use strict'; 'use strict';
return function (textbooksJson) { return function(textbooksJson) {
var textbooks = new TextbookCollection(textbooksJson, {parse: true}), var textbooks = new TextbookCollection(textbooksJson, {parse: true}),
tbView = new ListTextbooksView({collection: textbooks}); tbView = new ListTextbooksView({collection: textbooks});
...@@ -12,7 +12,7 @@ define([ ...@@ -12,7 +12,7 @@ define([
}); });
$(window).on('beforeunload', function() { $(window).on('beforeunload', function() {
var dirty = textbooks.find(function(textbook) { return textbook.isDirty(); }); var dirty = textbooks.find(function(textbook) { return textbook.isDirty(); });
if(dirty) { if (dirty) {
return gettext('You have unsaved changes. Do you really want to leave this page?'); return gettext('You have unsaved changes. Do you really want to leave this page?');
} }
}); });
......
define( define(
["jquery", "backbone", "js/views/active_video_upload_list", "js/views/previous_video_upload_list"], ['jquery', 'backbone', 'js/views/active_video_upload_list', 'js/views/previous_video_upload_list'],
function ($, Backbone, ActiveVideoUploadListView, PreviousVideoUploadListView) { function($, Backbone, ActiveVideoUploadListView, PreviousVideoUploadListView) {
"use strict"; 'use strict';
var VideosIndexFactory = function( var VideosIndexFactory = function(
$contentWrapper, $contentWrapper,
postUrl, postUrl,
......
define(["js/views/xblock_validation", "js/models/xblock_validation"], define(['js/views/xblock_validation', 'js/models/xblock_validation'],
function (XBlockValidationView, XBlockValidationModel) { function(XBlockValidationView, XBlockValidationModel) {
'use strict'; 'use strict';
return function (validationMessages, hasEditingUrl, isRoot, validationEle) { return function(validationMessages, hasEditingUrl, isRoot, validationEle) {
if (hasEditingUrl && !isRoot) { if (hasEditingUrl && !isRoot) {
validationMessages.showSummaryOnly = true; validationMessages.showSummaryOnly = true;
} }
var model = new XBlockValidationModel(validationMessages, {parse: true}); var model = new XBlockValidationModel(validationMessages, {parse: true});
if (!model.get("empty")) { if (!model.get('empty')) {
new XBlockValidationView({el: validationEle, model: model, root: isRoot}).render(); new XBlockValidationView({el: validationEle, model: model, root: isRoot}).render();
} }
}; };
......
define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/views/utils/create_course_utils", define(['domReady', 'jquery', 'underscore', 'js/utils/cancel_on_escape', 'js/views/utils/create_course_utils',
"js/views/utils/create_library_utils", "common/js/components/utils/view_utils"], 'js/views/utils/create_library_utils', 'common/js/components/utils/view_utils'],
function (domReady, $, _, CancelOnEscape, CreateCourseUtilsFactory, CreateLibraryUtilsFactory, ViewUtils) { function(domReady, $, _, CancelOnEscape, CreateCourseUtilsFactory, CreateLibraryUtilsFactory, ViewUtils) {
"use strict"; 'use strict';
var CreateCourseUtils = new CreateCourseUtilsFactory({ var CreateCourseUtils = new CreateCourseUtilsFactory({
name: '.new-course-name', name: '.new-course-name',
org: '.new-course-org', org: '.new-course-org',
...@@ -39,7 +39,7 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/vie ...@@ -39,7 +39,7 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/vie
error: 'error' error: 'error'
}); });
var saveNewCourse = function (e) { var saveNewCourse = function(e) {
e.preventDefault(); e.preventDefault();
if (CreateCourseUtils.hasInvalidRequiredFields()) { if (CreateCourseUtils.hasInvalidRequiredFields()) {
...@@ -60,27 +60,27 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/vie ...@@ -60,27 +60,27 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/vie
}; };
analytics.track('Created a Course', course_info); analytics.track('Created a Course', course_info);
CreateCourseUtils.create(course_info, function (errorMessage) { CreateCourseUtils.create(course_info, function(errorMessage) {
$('.create-course .wrap-error').addClass('is-shown'); $('.create-course .wrap-error').addClass('is-shown');
$('#course_creation_error').html('<p>' + errorMessage + '</p>'); $('#course_creation_error').html('<p>' + errorMessage + '</p>');
$('.new-course-save').addClass('is-disabled').attr('aria-disabled', true); $('.new-course-save').addClass('is-disabled').attr('aria-disabled', true);
}); });
}; };
var makeCancelHandler = function (addType) { var makeCancelHandler = function(addType) {
return function(e) { return function(e) {
e.preventDefault(); e.preventDefault();
$('.new-'+addType+'-button').removeClass('is-disabled').attr('aria-disabled', false); $('.new-' + addType + '-button').removeClass('is-disabled').attr('aria-disabled', false);
$('.wrapper-create-'+addType).removeClass('is-shown'); $('.wrapper-create-' + addType).removeClass('is-shown');
// Clear out existing fields and errors // Clear out existing fields and errors
$('#create-'+addType+'-form input[type=text]').val(''); $('#create-' + addType + '-form input[type=text]').val('');
$('#'+addType+'_creation_error').html(''); $('#' + addType + '_creation_error').html('');
$('.create-'+addType+' .wrap-error').removeClass('is-shown'); $('.create-' + addType + ' .wrap-error').removeClass('is-shown');
$('.new-'+addType+'-save').off('click'); $('.new-' + addType + '-save').off('click');
}; };
}; };
var addNewCourse = function (e) { var addNewCourse = function(e) {
e.preventDefault(); e.preventDefault();
$('.new-course-button').addClass('is-disabled').attr('aria-disabled', true); $('.new-course-button').addClass('is-disabled').attr('aria-disabled', true);
$('.new-course-save').addClass('is-disabled').attr('aria-disabled', true); $('.new-course-save').addClass('is-disabled').attr('aria-disabled', true);
...@@ -95,7 +95,7 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/vie ...@@ -95,7 +95,7 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/vie
CreateCourseUtils.configureHandlers(); CreateCourseUtils.configureHandlers();
}; };
var saveNewLibrary = function (e) { var saveNewLibrary = function(e) {
e.preventDefault(); e.preventDefault();
if (CreateLibraryUtils.hasInvalidRequiredFields()) { if (CreateLibraryUtils.hasInvalidRequiredFields()) {
...@@ -110,18 +110,18 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/vie ...@@ -110,18 +110,18 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/vie
var lib_info = { var lib_info = {
org: org, org: org,
number: number, number: number,
display_name: display_name, display_name: display_name
}; };
analytics.track('Created a Library', lib_info); analytics.track('Created a Library', lib_info);
CreateLibraryUtils.create(lib_info, function (errorMessage) { CreateLibraryUtils.create(lib_info, function(errorMessage) {
$('.create-library .wrap-error').addClass('is-shown'); $('.create-library .wrap-error').addClass('is-shown');
$('#library_creation_error').html('<p>' + errorMessage + '</p>'); $('#library_creation_error').html('<p>' + errorMessage + '</p>');
$('.new-library-save').addClass('is-disabled').attr('aria-disabled', true); $('.new-library-save').addClass('is-disabled').attr('aria-disabled', true);
}); });
}; };
var addNewLibrary = function (e) { var addNewLibrary = function(e) {
e.preventDefault(); e.preventDefault();
$('.new-library-button').addClass('is-disabled').attr('aria-disabled', true); $('.new-library-button').addClass('is-disabled').attr('aria-disabled', true);
$('.new-library-save').addClass('is-disabled').attr('aria-disabled', true); $('.new-library-save').addClass('is-disabled').attr('aria-disabled', true);
...@@ -137,22 +137,22 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/vie ...@@ -137,22 +137,22 @@ define(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape", "js/vie
}; };
var showTab = function(tab) { var showTab = function(tab) {
return function(e) { return function(e) {
e.preventDefault(); e.preventDefault();
$('.courses-tab').toggleClass('active', tab === 'courses'); $('.courses-tab').toggleClass('active', tab === 'courses');
$('.libraries-tab').toggleClass('active', tab === 'libraries'); $('.libraries-tab').toggleClass('active', tab === 'libraries');
$('.programs-tab').toggleClass('active', tab === 'programs'); $('.programs-tab').toggleClass('active', tab === 'programs');
// Also toggle this course-related notice shown below the course tab, if it is present: // Also toggle this course-related notice shown below the course tab, if it is present:
$('.wrapper-creationrights').toggleClass('is-hidden', tab !== 'courses'); $('.wrapper-creationrights').toggleClass('is-hidden', tab !== 'courses');
}; };
}; };
var onReady = function () { var onReady = function() {
$('.new-course-button').bind('click', addNewCourse); $('.new-course-button').bind('click', addNewCourse);
$('.new-library-button').bind('click', addNewLibrary); $('.new-library-button').bind('click', addNewLibrary);
$('.dismiss-button').bind('click', ViewUtils.deleteNotificationHandler(function () { $('.dismiss-button').bind('click', ViewUtils.deleteNotificationHandler(function() {
ViewUtils.reload(); ViewUtils.reload();
})); }));
......
define( define(
["backbone", "gettext"], ['backbone', 'gettext'],
function(Backbone, gettext) { function(Backbone, gettext) {
"use strict"; 'use strict';
var statusStrings = { var statusStrings = {
// Translators: This is the status of a video upload that is queued // Translators: This is the status of a video upload that is queued
// waiting for other uploads to complete // waiting for other uploads to complete
STATUS_QUEUED: gettext("Queued"), STATUS_QUEUED: gettext('Queued'),
// Translators: This is the status of an active video upload // Translators: This is the status of an active video upload
STATUS_UPLOADING: gettext("Uploading"), STATUS_UPLOADING: gettext('Uploading'),
// Translators: This is the status of a video upload that has // Translators: This is the status of a video upload that has
// completed successfully // completed successfully
STATUS_COMPLETED: gettext("Upload completed"), STATUS_COMPLETED: gettext('Upload completed'),
// Translators: This is the status of a video upload that has failed // Translators: This is the status of a video upload that has failed
STATUS_FAILED: gettext("Upload failed") STATUS_FAILED: gettext('Upload failed')
}; };
var ActiveVideoUpload = Backbone.Model.extend( var ActiveVideoUpload = Backbone.Model.extend(
......
define(["backbone"], function(Backbone) { define(['backbone'], function(Backbone) {
/** /**
* Simple model for an asset. * Simple model for an asset.
*/ */
var Asset = Backbone.Model.extend({ var Asset = Backbone.Model.extend({
defaults: { defaults: {
display_name: "", display_name: '',
content_type: "", content_type: '',
thumbnail: "", thumbnail: '',
date_added: "", date_added: '',
url: "", url: '',
external_url: "", external_url: '',
portable_url: "", portable_url: '',
locked: false locked: false
}, },
get_extension: function(){ get_extension: function() {
var name_segments = this.get("display_name").split(".").reverse(); var name_segments = this.get('display_name').split('.').reverse();
var asset_type = (name_segments.length > 1) ? name_segments[0].toUpperCase() : ""; var asset_type = (name_segments.length > 1) ? name_segments[0].toUpperCase() : '';
return asset_type; return asset_type;
} }
}); });
return Asset; return Asset;
}); });
define(["backbone", "underscore"], function(Backbone, _) { define(['backbone', 'underscore'], function(Backbone, _) {
var AssignmentGrade = Backbone.Model.extend({ var AssignmentGrade = Backbone.Model.extend({
defaults : { defaults: {
graderType : null, // the type label (string). May be "notgraded" which implies None. graderType: null, // the type label (string). May be "notgraded" which implies None.
locator : null // locator for the block locator: null // locator for the block
}, },
idAttribute: 'locator', idAttribute: 'locator',
urlRoot : '/xblock/', urlRoot: '/xblock/',
url: function() { url: function() {
// add ?fields=graderType to the request url (only needed for fetch, but innocuous for others) // add ?fields=graderType to the request url (only needed for fetch, but innocuous for others)
return Backbone.Model.prototype.url.apply(this) + '?' + $.param({fields: 'graderType'}); return Backbone.Model.prototype.url.apply(this) + '?' + $.param({fields: 'graderType'});
......
define(["backbone", "gettext", "backbone.associations"], function(Backbone, gettext) { define(['backbone', 'gettext', 'backbone.associations'], function(Backbone, gettext) {
var Chapter = Backbone.AssociatedModel.extend({ var Chapter = Backbone.AssociatedModel.extend({
defaults: function() { defaults: function() {
return { return {
name: "", name: '',
asset_path: "", asset_path: '',
order: this.collection ? this.collection.nextOrder() : 1 order: this.collection ? this.collection.nextOrder() : 1
}; };
}, },
...@@ -11,11 +11,11 @@ define(["backbone", "gettext", "backbone.associations"], function(Backbone, gett ...@@ -11,11 +11,11 @@ define(["backbone", "gettext", "backbone.associations"], function(Backbone, gett
return !this.get('name') && !this.get('asset_path'); return !this.get('name') && !this.get('asset_path');
}, },
parse: function(response) { parse: function(response) {
if("title" in response && !("name" in response)) { if ('title' in response && !('name' in response)) {
response.name = response.title; response.name = response.title;
delete response.title; delete response.title;
} }
if("url" in response && !("asset_path" in response)) { if ('url' in response && !('asset_path' in response)) {
response.asset_path = response.url; response.asset_path = response.url;
delete response.url; delete response.url;
} }
...@@ -30,19 +30,19 @@ define(["backbone", "gettext", "backbone.associations"], function(Backbone, gett ...@@ -30,19 +30,19 @@ define(["backbone", "gettext", "backbone.associations"], function(Backbone, gett
// NOTE: validation functions should return non-internationalized error // NOTE: validation functions should return non-internationalized error
// messages. The messages will be passed through gettext in the template. // messages. The messages will be passed through gettext in the template.
validate: function(attrs, options) { validate: function(attrs, options) {
if(!attrs.name && !attrs.asset_path) { if (!attrs.name && !attrs.asset_path) {
return { return {
message: gettext("Chapter name and asset_path are both required"), message: gettext('Chapter name and asset_path are both required'),
attributes: {name: true, asset_path: true} attributes: {name: true, asset_path: true}
}; };
} else if(!attrs.name) { } else if (!attrs.name) {
return { return {
message: gettext("Chapter name is required"), message: gettext('Chapter name is required'),
attributes: {name: true} attributes: {name: true}
}; };
} else if (!attrs.asset_path) { } else if (!attrs.asset_path) {
return { return {
message: gettext("asset_path is required"), message: gettext('asset_path is required'),
attributes: {asset_path: true} attributes: {asset_path: true}
}; };
} }
......
define(["backbone"], function(Backbone) { define(['backbone'], function(Backbone) {
var Checklist = Backbone.Model.extend({ var Checklist = Backbone.Model.extend({
}); });
return Checklist; return Checklist;
......
/** /**
* Simple model for adding a component of a given type (for example, "video" or "html"). * Simple model for adding a component of a given type (for example, "video" or "html").
*/ */
define(["backbone"], function (Backbone) { define(['backbone'], function(Backbone) {
return Backbone.Model.extend({ return Backbone.Model.extend({
defaults: { defaults: {
type: "", type: '',
// Each entry in the template array is an Object with the following keys: // Each entry in the template array is an Object with the following keys:
// display_name // display_name
// category (may or may not match "type") // category (may or may not match "type")
...@@ -13,7 +13,7 @@ define(["backbone"], function (Backbone) { ...@@ -13,7 +13,7 @@ define(["backbone"], function (Backbone) {
templates: [], templates: [],
support_legend: {} support_legend: {}
}, },
parse: function (response) { parse: function(response) {
// Returns true only for templates that both have no boilerplate and are of // Returns true only for templates that both have no boilerplate and are of
// the overall type of the menu. This allows other component types to be added // the overall type of the menu. This allows other component types to be added
// and they will get sorted alphabetically rather than just at the top. // and they will get sorted alphabetically rather than just at the top.
...@@ -28,7 +28,7 @@ define(["backbone"], function (Backbone) { ...@@ -28,7 +28,7 @@ define(["backbone"], function (Backbone) {
this.support_legend = response.support_legend; this.support_legend = response.support_legend;
// Sort the templates. // Sort the templates.
this.templates.sort(function (a, b) { this.templates.sort(function(a, b) {
// The blank problem for the current type goes first // The blank problem for the current type goes first
if (isPrimaryBlankTemplate(a)) { if (isPrimaryBlankTemplate(a)) {
return -1; return -1;
......
define(['backbone'], function(Backbone){ define(['backbone'], function(Backbone) {
var Course = Backbone.Model.extend({ var Course = Backbone.Model.extend({
defaults: { defaults: {
"name": "" 'name': ''
}, },
validate: function(attrs, options) { validate: function(attrs, options) {
if (!attrs.name) { if (!attrs.name) {
return gettext("You must specify a name"); return gettext('You must specify a name');
} }
} }
}); });
......
define(["backbone"], function(Backbone) { define(['backbone'], function(Backbone) {
// single per course holds the updates and handouts // single per course holds the updates and handouts
var CourseInfo = Backbone.Model.extend({ var CourseInfo = Backbone.Model.extend({
// This model class is not suited for restful operations and is considered just a server side initialized container // This model class is not suited for restful operations and is considered just a server side initialized container
url: '', url: '',
defaults: { defaults: {
"updates" : null, // UpdateCollection 'updates': null, // UpdateCollection
"handouts": null // HandoutCollection 'handouts': null // HandoutCollection
} }
}); });
return CourseInfo; return CourseInfo;
}); });
define(["backbone", "jquery", "jquery.ui"], function(Backbone, $) { define(['backbone', 'jquery', 'jquery.ui'], function(Backbone, $) {
// course update -- biggest kludge here is the lack of a real id to map updates to originals // course update -- biggest kludge here is the lack of a real id to map updates to originals
var CourseUpdate = Backbone.Model.extend({ var CourseUpdate = Backbone.Model.extend({
defaults: { defaults: {
"date" : $.datepicker.formatDate('MM d, yy', new Date()), 'date': $.datepicker.formatDate('MM d, yy', new Date()),
"content" : "", 'content': '',
"push_notification_enabled": false, 'push_notification_enabled': false,
"push_notification_selected" : false 'push_notification_selected': false
}, },
validate: function(attrs) { validate: function(attrs) {
var date_exists = (attrs.date !== null && attrs.date !== ""); var date_exists = (attrs.date !== null && attrs.date !== '');
var date_is_valid_string = ($.datepicker.formatDate('MM d, yy', new Date(attrs.date)) === attrs.date); var date_is_valid_string = ($.datepicker.formatDate('MM d, yy', new Date(attrs.date)) === attrs.date);
if (!(date_exists && date_is_valid_string)) { if (!(date_exists && date_is_valid_string)) {
return {"date_required": gettext("Action required: Enter a valid date.")}; return {'date_required': gettext('Action required: Enter a valid date.')};
} }
} }
}); });
......
define(["js/models/xblock_info"], define(['js/models/xblock_info'],
function(XBlockInfo) { function(XBlockInfo) {
var CustomSyncXBlockInfo = XBlockInfo.extend({ var CustomSyncXBlockInfo = XBlockInfo.extend({
sync: function(method, model, options) { sync: function(method, model, options) {
......
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
* A model that simply allows the update URL to be passed * A model that simply allows the update URL to be passed
* in as an argument. * in as an argument.
*/ */
define(["backbone"], function(Backbone){ define(['backbone'], function(Backbone) {
return Backbone.Model.extend({ return Backbone.Model.extend({
defaults: { defaults: {
"explicit_url": "" 'explicit_url': ''
}, },
url: function() { url: function() {
return this.get("explicit_url"); return this.get('explicit_url');
} }
}); });
}); });
...@@ -12,13 +12,13 @@ define([ ...@@ -12,13 +12,13 @@ define([
usage: [] usage: []
}; };
}, },
url : function() { url: function() {
var parentModel = this.collection.parents[0]; var parentModel = this.collection.parents[0];
return parentModel.urlRoot + '/' + encodeURIComponent(parentModel.id) + '/' + encodeURIComponent(this.id); return parentModel.urlRoot + '/' + encodeURIComponent(parentModel.id) + '/' + encodeURIComponent(this.id);
}, },
reset: function() { reset: function() {
this.set(this._originalAttributes, { parse: true }); this.set(this._originalAttributes, {parse: true});
}, },
isEmpty: function() { isEmpty: function() {
...@@ -31,14 +31,14 @@ define([ ...@@ -31,14 +31,14 @@ define([
name: this.get('name'), name: this.get('name'),
version: this.get('version'), version: this.get('version'),
usage: this.get('usage') usage: this.get('usage')
}; };
}, },
validate: function(attrs) { validate: function(attrs) {
if (!str.trim(attrs.name)) { if (!str.trim(attrs.name)) {
return { return {
message: gettext('Group name is required'), message: gettext('Group name is required'),
attributes: { name: true } attributes: {name: true}
}; };
} }
} }
......
define(["backbone", "underscore"], function(Backbone, _) { define(['backbone', 'underscore'], function(Backbone, _) {
var LicenseModel = Backbone.Model.extend({ var LicenseModel = Backbone.Model.extend({
defaults: { defaults: {
"type": null, 'type': null,
"options": {}, 'options': {},
"custom": false // either `false`, or a string 'custom': false // either `false`, or a string
}, },
initialize: function(attributes) { initialize: function(attributes) {
if(attributes && attributes.asString) { if (attributes && attributes.asString) {
this.setFromString(attributes.asString); this.setFromString(attributes.asString);
this.unset("asString"); this.unset('asString');
} }
}, },
toString: function() { toString: function() {
var custom = this.get("custom"); var custom = this.get('custom');
if (custom) { if (custom) {
return custom; return custom;
} }
var type = this.get("type"), var type = this.get('type'),
options = this.get("options"); options = this.get('options');
if (_.isEmpty(options)) { if (_.isEmpty(options)) {
return type || ""; return type || '';
} }
// options are where it gets tricky // options are where it gets tricky
var optionStrings = _.map(options, function (value, key) { var optionStrings = _.map(options, function(value, key) {
if(_.isBoolean(value)) { if (_.isBoolean(value)) {
return value ? key : null return value ? key : null;
} else { } else {
return key + "=" + value return key + '=' + value;
} }
}); });
// filter out nulls // filter out nulls
optionStrings = _.filter(optionStrings, _.identity); optionStrings = _.filter(optionStrings, _.identity);
// build license string and return // build license string and return
return type + ": " + optionStrings.join(" "); return type + ': ' + optionStrings.join(' ');
}, },
setFromString: function(string, options) { setFromString: function(string, options) {
...@@ -46,8 +46,8 @@ define(["backbone", "underscore"], function(Backbone, _) { ...@@ -46,8 +46,8 @@ define(["backbone", "underscore"], function(Backbone, _) {
return this.set(this.defaults, options); return this.set(this.defaults, options);
} }
var colonIndex = string.indexOf(":"), var colonIndex = string.indexOf(':'),
spaceIndex = string.indexOf(" "); spaceIndex = string.indexOf(' ');
// a string without a colon could be a custom license, or a license // a string without a colon could be a custom license, or a license
// type without options // type without options
...@@ -55,16 +55,16 @@ define(["backbone", "underscore"], function(Backbone, _) { ...@@ -55,16 +55,16 @@ define(["backbone", "underscore"], function(Backbone, _) {
if (spaceIndex == -1) { if (spaceIndex == -1) {
// if there's no space, it's a license type without options // if there's no space, it's a license type without options
return this.set({ return this.set({
"type": string, 'type': string,
"options": {}, 'options': {},
"custom": false 'custom': false
}, options); }, options);
} else { } else {
// if there is a space, it's a custom license // if there is a space, it's a custom license
return this.set({ return this.set({
"type": null, 'type': null,
"options": {}, 'options': {},
"custom": string 'custom': string
}, options); }, options);
} }
} }
...@@ -74,24 +74,24 @@ define(["backbone", "underscore"], function(Backbone, _) { ...@@ -74,24 +74,24 @@ define(["backbone", "underscore"], function(Backbone, _) {
optionsObj = {}, optionsObj = {},
optionsString = string.substring(colonIndex + 1); optionsString = string.substring(colonIndex + 1);
_.each(optionsString.split(" "), function(optionString) { _.each(optionsString.split(' '), function(optionString) {
if (_.isEmpty(optionString)) { if (_.isEmpty(optionString)) {
return; return;
} }
var eqIndex = optionString.indexOf("="); var eqIndex = optionString.indexOf('=');
if(eqIndex == -1) { if (eqIndex == -1) {
// this is a boolean flag // this is a boolean flag
optionsObj[optionString] = true; optionsObj[optionString] = true;
} else { } else {
// this is a key-value pair // this is a key-value pair
var optionKey = optionString.substring(0, eqIndex); var optionKey = optionString.substring(0, eqIndex);
var optionVal = optionString.substring(eqIndex + 1); var optionVal = optionString.substring(eqIndex + 1);
optionsObj[optionKey] = optionVal; optionsObj[optionKey] = optionVal;
} }
}); });
return this.set({ return this.set({
"type": type, "options": optionsObj, "custom": false, 'type': type, 'options': optionsObj, 'custom': false
}, options); }, options);
} }
}); });
......
define(["backbone", "underscore"], function(Backbone, _) { define(['backbone', 'underscore'], function(Backbone, _) {
var Location = Backbone.Model.extend({ var Location = Backbone.Model.extend({
defaults: { defaults: {
tag: "", tag: '',
org: "", org: '',
course: "", course: '',
category: "", category: '',
name: "" name: ''
}, },
toUrl: function(overrides) { toUrl: function(overrides) {
return return;
(overrides && overrides['tag'] ? overrides['tag'] : this.get('tag')) + "://" + (overrides && overrides['tag'] ? overrides['tag'] : this.get('tag')) + '://' +
(overrides && overrides['org'] ? overrides['org'] : this.get('org')) + "/" + (overrides && overrides['org'] ? overrides['org'] : this.get('org')) + '/' +
(overrides && overrides['course'] ? overrides['course'] : this.get('course')) + "/" + (overrides && overrides['course'] ? overrides['course'] : this.get('course')) + '/' +
(overrides && overrides['category'] ? overrides['category'] : this.get('category')) + "/" + (overrides && overrides['category'] ? overrides['category'] : this.get('category')) + '/' +
(overrides && overrides['name'] ? overrides['name'] : this.get('name')) + "/"; (overrides && overrides['name'] ? overrides['name'] : this.get('name')) + '/';
}, },
_tagPattern : /[^:]+/g, _tagPattern: /[^:]+/g,
_fieldPattern : new RegExp('[^/]+','g'), _fieldPattern: new RegExp('[^/]+', 'g'),
parse: function(payload) { parse: function(payload) {
if (_.isArray(payload)) { if (_.isArray(payload)) {
...@@ -47,12 +47,12 @@ define(["backbone", "underscore"], function(Backbone, _) { ...@@ -47,12 +47,12 @@ define(["backbone", "underscore"], function(Backbone, _) {
return payload; return payload;
} }
}, },
getNextField : function(payload) { getNextField: function(payload) {
try { try {
return this._fieldPattern.exec(payload)[0]; return this._fieldPattern.exec(payload)[0];
} }
catch (err) { catch (err) {
return ""; return '';
} }
} }
}); });
......
define(["backbone"], function(Backbone) { define(['backbone'], function(Backbone) {
/** /**
* Model used for metadata setting editors. This model does not do its own saving, * Model used for metadata setting editors. This model does not do its own saving,
* as that is done by module_edit.coffee. * as that is done by module_edit.coffee.
*/ */
var Metadata = Backbone.Model.extend({ var Metadata = Backbone.Model.extend({
defaults: { defaults: {
"field_name": null, 'field_name': null,
"display_name": null, 'display_name': null,
"value" : null, 'value': null,
"explicitly_set": null, 'explicitly_set': null,
"default_value" : null, 'default_value': null,
"options" : null, 'options': null,
"type" : null 'type': null
}, },
initialize: function() { initialize: function() {
...@@ -23,7 +23,7 @@ define(["backbone"], function(Backbone) { ...@@ -23,7 +23,7 @@ define(["backbone"], function(Backbone) {
* Returns true if the stored value is different, or if the "explicitly_set" * Returns true if the stored value is different, or if the "explicitly_set"
* property has changed. * property has changed.
*/ */
isModified : function() { isModified: function() {
if (!this.get('explicitly_set') && !this.original_explicitly_set) { if (!this.get('explicitly_set') && !this.original_explicitly_set) {
return false; return false;
} }
...@@ -43,7 +43,7 @@ define(["backbone"], function(Backbone) { ...@@ -43,7 +43,7 @@ define(["backbone"], function(Backbone) {
/** /**
* The value, as shown in the UI. This may be an inherited or default value. * The value, as shown in the UI. This may be an inherited or default value.
*/ */
getDisplayValue : function () { getDisplayValue: function() {
return this.get('value'); return this.get('value');
}, },
...@@ -59,7 +59,7 @@ define(["backbone"], function(Backbone) { ...@@ -59,7 +59,7 @@ define(["backbone"], function(Backbone) {
/** /**
* Sets the displayed value. * Sets the displayed value.
*/ */
setValue: function (value) { setValue: function(value) {
this.set({ this.set({
explicitly_set: true, explicitly_set: true,
value: value value: value
...@@ -70,7 +70,7 @@ define(["backbone"], function(Backbone) { ...@@ -70,7 +70,7 @@ define(["backbone"], function(Backbone) {
* Returns the field name, which should be used for persisting the metadata * Returns the field name, which should be used for persisting the metadata
* field to the server. * field to the server.
*/ */
getFieldName: function () { getFieldName: function() {
return this.get('field_name'); return this.get('field_name');
}, },
...@@ -78,7 +78,7 @@ define(["backbone"], function(Backbone) { ...@@ -78,7 +78,7 @@ define(["backbone"], function(Backbone) {
* Returns the options. This may be a array of possible values, or an object * Returns the options. This may be a array of possible values, or an object
* with properties like "max", "min" and "step". * with properties like "max", "min" and "step".
*/ */
getOptions: function () { getOptions: function() {
return this.get('options'); return this.get('options');
}, },
...@@ -102,14 +102,14 @@ define(["backbone"], function(Backbone) { ...@@ -102,14 +102,14 @@ define(["backbone"], function(Backbone) {
} }
}); });
Metadata.SELECT_TYPE = "Select"; Metadata.SELECT_TYPE = 'Select';
Metadata.INTEGER_TYPE = "Integer"; Metadata.INTEGER_TYPE = 'Integer';
Metadata.FLOAT_TYPE = "Float"; Metadata.FLOAT_TYPE = 'Float';
Metadata.GENERIC_TYPE = "Generic"; Metadata.GENERIC_TYPE = 'Generic';
Metadata.LIST_TYPE = "List"; Metadata.LIST_TYPE = 'List';
Metadata.DICT_TYPE = "Dict"; Metadata.DICT_TYPE = 'Dict';
Metadata.VIDEO_LIST_TYPE = "VideoList"; Metadata.VIDEO_LIST_TYPE = 'VideoList';
Metadata.RELATIVE_TIME_TYPE = "RelativeTime"; Metadata.RELATIVE_TIME_TYPE = 'RelativeTime';
return Metadata; return Metadata;
}); });
define(["backbone", "js/utils/module"], function(Backbone, ModuleUtils) { define(['backbone', 'js/utils/module'], function(Backbone, ModuleUtils) {
var ModuleInfo = Backbone.Model.extend({ var ModuleInfo = Backbone.Model.extend({
urlRoot: ModuleUtils.urlRoot, urlRoot: ModuleUtils.urlRoot,
defaults: { defaults: {
"id": null, 'id': null,
"data": null, 'data': null,
"metadata" : null, 'metadata': null,
"children" : null 'children': null
} }
}); });
return ModuleInfo; return ModuleInfo;
}); });
define(["backbone", "gettext", "common/js/components/views/feedback_notification", "js/utils/module"], define(['backbone', 'gettext', 'common/js/components/views/feedback_notification', 'js/utils/module'],
function(Backbone, gettext, NotificationView, ModuleUtils) { function(Backbone, gettext, NotificationView, ModuleUtils) {
var Section = Backbone.Model.extend({
var Section = Backbone.Model.extend({ defaults: {
defaults: { 'name': ''
"name": "" },
}, validate: function(attrs, options) {
validate: function(attrs, options) { if (!attrs.name) {
if (!attrs.name) { return gettext('You must specify a name');
return gettext("You must specify a name"); }
} },
}, urlRoot: ModuleUtils.urlRoot,
urlRoot: ModuleUtils.urlRoot, toJSON: function() {
toJSON: function() { return {
return { metadata: {
metadata: { display_name: this.get('name')
display_name: this.get("name") }
};
},
initialize: function() {
this.listenTo(this, 'request', this.showNotification);
this.listenTo(this, 'sync', this.hideNotification);
},
showNotification: function() {
if (!this.msg) {
this.msg = new NotificationView.Mini({
title: gettext('Saving')
});
} }
}; this.msg.show();
}, },
initialize: function() { hideNotification: function() {
this.listenTo(this, "request", this.showNotification); if (!this.msg) { return; }
this.listenTo(this, "sync", this.hideNotification); this.msg.hide();
},
showNotification: function() {
if(!this.msg) {
this.msg = new NotificationView.Mini({
title: gettext("Saving")
});
} }
this.msg.show(); });
}, return Section;
hideNotification: function() {
if(!this.msg) { return; }
this.msg.hide();
}
}); });
return Section;
});
define(["backbone"], function(Backbone) { define(['backbone'], function(Backbone) {
var Advanced = Backbone.Model.extend({
var Advanced = Backbone.Model.extend({ defaults: {
defaults: {
// There will be one property per course setting. Each property's value is an object with keys // There will be one property per course setting. Each property's value is an object with keys
// 'display_name', 'help', 'value', and 'deprecated. The property keys are the setting names. // 'display_name', 'help', 'value', and 'deprecated. The property keys are the setting names.
// For instance: advanced_modules: {display_name: "Advanced Modules, help:"Beta modules...", // For instance: advanced_modules: {display_name: "Advanced Modules, help:"Beta modules...",
// value: ["word_cloud", "split_module"], deprecated: False} // value: ["word_cloud", "split_module"], deprecated: False}
// Only 'value' is editable. // Only 'value' is editable.
}, },
validate: function (attrs) { validate: function(attrs) {
// Keys can no longer be edited. We are currently not validating values. // Keys can no longer be edited. We are currently not validating values.
} }
}); });
return Advanced; return Advanced;
}); // end define() }); // end define()
define(["backbone", "underscore", "gettext", "js/models/validation_helpers", "js/utils/date_utils"], define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js/utils/date_utils'],
function(Backbone, _, gettext, ValidationHelpers, DateUtils) { function(Backbone, _, gettext, ValidationHelpers, DateUtils) {
var CourseDetails = Backbone.Model.extend({
defaults: {
org: '',
course_id: '',
run: '',
language: '',
start_date: null, // maps to 'start'
end_date: null, // maps to 'end'
enrollment_start: null,
enrollment_end: null,
syllabus: null,
title: '',
subtitle: '',
duration: '',
description: '',
short_description: '',
overview: '',
intro_video: null,
effort: null, // an int or null,
license: null,
course_image_name: '', // the filename
course_image_asset_path: '', // the full URL (/c4x/org/course/num/asset/filename)
banner_image_name: '',
banner_image_asset_path: '',
video_thumbnail_image_name: '',
video_thumbnail_image_asset_path: '',
pre_requisite_courses: [],
entrance_exam_enabled: '',
entrance_exam_minimum_score_pct: '50',
learning_info: [],
instructor_info: {}
},
var CourseDetails = Backbone.Model.extend({ validate: function(newattrs) {
defaults: {
org : '',
course_id: '',
run: '',
language: '',
start_date: null, // maps to 'start'
end_date: null, // maps to 'end'
enrollment_start: null,
enrollment_end: null,
syllabus: null,
title: "",
subtitle: "",
duration: "",
description: "",
short_description: "",
overview: "",
intro_video: null,
effort: null, // an int or null,
license: null,
course_image_name: '', // the filename
course_image_asset_path: '', // the full URL (/c4x/org/course/num/asset/filename)
banner_image_name: '',
banner_image_asset_path: '',
video_thumbnail_image_name: '',
video_thumbnail_image_asset_path: '',
pre_requisite_courses: [],
entrance_exam_enabled : '',
entrance_exam_minimum_score_pct: '50',
learning_info: [],
instructor_info: {}
},
validate: function(newattrs) {
// Returns either nothing (no return call) so that validate works or an object of {field: errorstring} pairs // Returns either nothing (no return call) so that validate works or an object of {field: errorstring} pairs
// A bit funny in that the video key validation is asynchronous; so, it won't stop the validation. // A bit funny in that the video key validation is asynchronous; so, it won't stop the validation.
var errors = {}; var errors = {};
newattrs = DateUtils.convertDateStringsToObjects( newattrs = DateUtils.convertDateStringsToObjects(
newattrs, ["start_date", "end_date", "enrollment_start", "enrollment_end"] newattrs, ['start_date', 'end_date', 'enrollment_start', 'enrollment_end']
); );
if (newattrs.start_date === null) { if (newattrs.start_date === null) {
errors.start_date = gettext("The course must have an assigned start date."); errors.start_date = gettext('The course must have an assigned start date.');
} }
if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) { if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) {
errors.end_date = gettext("The course end date must be later than the course start date."); errors.end_date = gettext('The course end date must be later than the course start date.');
} }
if (newattrs.start_date && newattrs.enrollment_start && newattrs.start_date < newattrs.enrollment_start) { if (newattrs.start_date && newattrs.enrollment_start && newattrs.start_date < newattrs.enrollment_start) {
errors.enrollment_start = gettext("The course start date must be later than the enrollment start date."); errors.enrollment_start = gettext('The course start date must be later than the enrollment start date.');
} }
if (newattrs.enrollment_start && newattrs.enrollment_end && newattrs.enrollment_start >= newattrs.enrollment_end) { if (newattrs.enrollment_start && newattrs.enrollment_end && newattrs.enrollment_start >= newattrs.enrollment_end) {
errors.enrollment_end = gettext("The enrollment start date cannot be after the enrollment end date."); errors.enrollment_end = gettext('The enrollment start date cannot be after the enrollment end date.');
} }
if (newattrs.end_date && newattrs.enrollment_end && newattrs.end_date < newattrs.enrollment_end) { if (newattrs.end_date && newattrs.enrollment_end && newattrs.end_date < newattrs.enrollment_end) {
errors.enrollment_end = gettext("The enrollment end date cannot be after the course end date."); errors.enrollment_end = gettext('The enrollment end date cannot be after the course end date.');
} }
if (newattrs.intro_video && newattrs.intro_video !== this.get('intro_video')) { if (newattrs.intro_video && newattrs.intro_video !== this.get('intro_video')) {
if (this._videokey_illegal_chars.exec(newattrs.intro_video)) { if (this._videokey_illegal_chars.exec(newattrs.intro_video)) {
errors.intro_video = gettext("Key should only contain letters, numbers, _, or -"); errors.intro_video = gettext('Key should only contain letters, numbers, _, or -');
} }
// TODO check if key points to a real video using google's youtube api // TODO check if key points to a real video using google's youtube api
} }
if(_.has(newattrs, 'entrance_exam_minimum_score_pct')){ if (_.has(newattrs, 'entrance_exam_minimum_score_pct')) {
var range = { var range = {
min: 1, min: 1,
max: 100 max: 100
}; };
if(!ValidationHelpers.validateIntegerRange(newattrs.entrance_exam_minimum_score_pct, range)){ if (!ValidationHelpers.validateIntegerRange(newattrs.entrance_exam_minimum_score_pct, range)) {
errors.entrance_exam_minimum_score_pct = interpolate(gettext("Please enter an integer between %(min)s and %(max)s."), range, true); errors.entrance_exam_minimum_score_pct = interpolate(gettext('Please enter an integer between %(min)s and %(max)s.'), range, true);
} }
} }
if (!_.isEmpty(errors)) return errors; if (!_.isEmpty(errors)) return errors;
// NOTE don't return empty errors as that will be interpreted as an error state // NOTE don't return empty errors as that will be interpreted as an error state
}, },
_videokey_illegal_chars : /[^a-zA-Z0-9_-]/g, _videokey_illegal_chars: /[^a-zA-Z0-9_-]/g,
set_videosource: function(newsource) { set_videosource: function(newsource) {
// newsource either is <video youtube="speed:key, *"/> or just the "speed:key, *" string // newsource either is <video youtube="speed:key, *"/> or just the "speed:key, *" string
// returns the videosource for the preview which iss the key whose speed is closest to 1 // returns the videosource for the preview which iss the key whose speed is closest to 1
if (_.isEmpty(newsource) && !_.isEmpty(this.get('intro_video'))) this.set({'intro_video': null}, {validate: true}); if (_.isEmpty(newsource) && !_.isEmpty(this.get('intro_video'))) this.set({'intro_video': null}, {validate: true});
// TODO remove all whitespace w/in string // TODO remove all whitespace w/in string
else { else {
if (this.get('intro_video') !== newsource) this.set('intro_video', newsource, {validate: true}); if (this.get('intro_video') !== newsource) this.set('intro_video', newsource, {validate: true});
} }
return this.videosourceSample(); return this.videosourceSample();
}, },
videosourceSample : function() { videosourceSample: function() {
if (this.has('intro_video')) return "//www.youtube.com/embed/" + this.get('intro_video'); if (this.has('intro_video')) return '//www.youtube.com/embed/' + this.get('intro_video');
else return ""; else return '';
}, },
// Whether or not the course pacing can be toggled. If the course // Whether or not the course pacing can be toggled. If the course
// has already started, returns false; otherwise, returns true. // has already started, returns false; otherwise, returns true.
canTogglePace: function () { canTogglePace: function() {
return new Date() <= new Date(this.get('start_date')); return new Date() <= new Date(this.get('start_date'));
} }
}); });
return CourseDetails;
}); // end define() return CourseDetails;
}); // end define()
define(["backbone", "underscore", "gettext"], function(Backbone, _, gettext) { define(['backbone', 'underscore', 'gettext'], function(Backbone, _, gettext) {
var CourseGrader = Backbone.Model.extend({
var CourseGrader = Backbone.Model.extend({ defaults: {
defaults: { 'type': '', // must be unique w/in collection (ie. w/in course)
"type" : "", // must be unique w/in collection (ie. w/in course) 'min_count': 1,
"min_count" : 1, 'drop_count': 0,
"drop_count" : 0, 'short_label': '', // what to use in place of type if space is an issue
"short_label" : "", // what to use in place of type if space is an issue 'weight': 0 // int 0..100
"weight" : 0 // int 0..100 },
}, parse: function(attrs) {
parse : function(attrs) {
// round off values while converting them to integer // round off values while converting them to integer
if (attrs['weight']) { if (attrs['weight']) {
attrs.weight = Math.round(attrs.weight); attrs.weight = Math.round(attrs.weight);
}
if (attrs['min_count']) {
attrs.min_count = Math.round(attrs.min_count);
}
if (attrs['drop_count']) {
attrs.drop_count = Math.round(attrs.drop_count);
}
return attrs;
},
validate : function(attrs) {
var errors = {};
if (_.has(attrs, 'type')) {
if (_.isEmpty(attrs['type'])) {
errors.type = "The assignment type must have a name.";
} }
else { if (attrs['min_count']) {
attrs.min_count = Math.round(attrs.min_count);
}
if (attrs['drop_count']) {
attrs.drop_count = Math.round(attrs.drop_count);
}
return attrs;
},
validate: function(attrs) {
var errors = {};
if (_.has(attrs, 'type')) {
if (_.isEmpty(attrs['type'])) {
errors.type = 'The assignment type must have a name.';
}
else {
// FIXME somehow this.collection is unbound sometimes. I can't track down when // FIXME somehow this.collection is unbound sometimes. I can't track down when
var existing = this.collection && this.collection.some(function(other) { return (other.cid != this.cid) && (other.get('type') == attrs['type']);}, this); var existing = this.collection && this.collection.some(function(other) { return (other.cid != this.cid) && (other.get('type') == attrs['type']); }, this);
if (existing) { if (existing) {
errors.type = gettext("There's already another assignment type with this name."); errors.type = gettext("There's already another assignment type with this name.");
}
} }
} }
} if (_.has(attrs, 'weight')) {
if (_.has(attrs, 'weight')) { var intWeight = Math.round(attrs.weight); // see if this ensures value saved is int
var intWeight = Math.round(attrs.weight); // see if this ensures value saved is int if (!isFinite(intWeight) || /\D+/.test(attrs.weight) || intWeight < 0 || intWeight > 100) {
if (!isFinite(intWeight) || /\D+/.test(attrs.weight) || intWeight < 0 || intWeight > 100) { errors.weight = gettext('Please enter an integer between 0 and 100.');
errors.weight = gettext("Please enter an integer between 0 and 100."); }
} else {
else { attrs.weight = intWeight;
attrs.weight = intWeight; if (this.collection && attrs.weight > 0) {
if (this.collection && attrs.weight > 0) {
// FIXME b/c saves don't update the models if validation fails, we should // FIXME b/c saves don't update the models if validation fails, we should
// either revert the field value to the one in the model and make them make room // either revert the field value to the one in the model and make them make room
// or figure out a holistic way to balance the vals across the whole // or figure out a holistic way to balance the vals across the whole
// if ((this.collection.sumWeights() + attrs.weight - this.get('weight')) > 100) // if ((this.collection.sumWeights() + attrs.weight - this.get('weight')) > 100)
// errors.weight = "The weights cannot add to more than 100."; // errors.weight = "The weights cannot add to more than 100.";
}
} }
if (_.has(attrs, 'min_count')) {
var intMinCount = Math.round(attrs.min_count);
if (!isFinite(intMinCount) || /\D+/.test(attrs.min_count) || intMinCount < 1) {
errors.min_count = gettext('Please enter an integer greater than 0.');
} }
}} else attrs.min_count = intMinCount;
if (_.has(attrs, 'min_count')) {
var intMinCount = Math.round(attrs.min_count);
if (!isFinite(intMinCount) || /\D+/.test(attrs.min_count) || intMinCount < 1) {
errors.min_count = gettext("Please enter an integer greater than 0.");
} }
else attrs.min_count = intMinCount; if (_.has(attrs, 'drop_count')) {
} var dropCount = attrs.drop_count;
if (_.has(attrs, 'drop_count')) { var intDropCount = Math.round(dropCount);
var dropCount = attrs.drop_count; if (!isFinite(intDropCount) || /\D+/.test(dropCount) || (_.isString(dropCount) && _.isEmpty(dropCount.trim())) || intDropCount < 0) {
var intDropCount = Math.round(dropCount); errors.drop_count = gettext('Please enter non-negative integer.');
if (!isFinite(intDropCount) || /\D+/.test(dropCount) || (_.isString(dropCount) && _.isEmpty(dropCount.trim())) || intDropCount < 0) { }
errors.drop_count = gettext("Please enter non-negative integer."); else attrs.drop_count = intDropCount;
} }
else attrs.drop_count = intDropCount; if (_.has(attrs, 'min_count') && _.has(attrs, 'drop_count') && !_.has(errors, 'min_count') && !_.has(errors, 'drop_count') && attrs.drop_count > attrs.min_count) {
} var template = _.template(
if (_.has(attrs, 'min_count') && _.has(attrs, 'drop_count') && !_.has(errors, 'min_count') && !_.has(errors, 'drop_count') && attrs.drop_count > attrs.min_count) { gettext('Cannot drop more <%= types %> assignments than are assigned.')
var template = _.template(
gettext("Cannot drop more <%= types %> assignments than are assigned.")
); );
errors.drop_count = template({types: attrs.type}); errors.drop_count = template({types: attrs.type});
}
if (!_.isEmpty(errors)) return errors;
} }
if (!_.isEmpty(errors)) return errors; });
}
});
return CourseGrader; return CourseGrader;
}); // end define() }); // end define()
define(["backbone", "js/models/location", "js/collections/course_grader"], define(['backbone', 'js/models/location', 'js/collections/course_grader'],
function(Backbone, Location, CourseGraderCollection) { function(Backbone, Location, CourseGraderCollection) {
var CourseGradingPolicy = Backbone.Model.extend({
var CourseGradingPolicy = Backbone.Model.extend({ defaults: {
defaults : { graders: null, // CourseGraderCollection
graders : null, // CourseGraderCollection grade_cutoffs: null, // CourseGradeCutoff model
grade_cutoffs : null, // CourseGradeCutoff model grace_period: null, // either null or { hours: n, minutes: m, ...}
grace_period : null, // either null or { hours: n, minutes: m, ...} minimum_grade_credit: null // either null or percentage
minimum_grade_credit : null // either null or percentage },
}, parse: function(attributes) {
parse: function(attributes) { if (attributes['graders']) {
if (attributes['graders']) { var graderCollection;
var graderCollection;
// interesting race condition: if {parse:true} when newing, then parse called before .attributes created // interesting race condition: if {parse:true} when newing, then parse called before .attributes created
if (this.attributes && this.has('graders')) { if (this.attributes && this.has('graders')) {
graderCollection = this.get('graders'); graderCollection = this.get('graders');
graderCollection.reset(attributes.graders, {parse:true}); graderCollection.reset(attributes.graders, {parse: true});
} }
else { else {
graderCollection = new CourseGraderCollection(attributes.graders, {parse:true}); graderCollection = new CourseGraderCollection(attributes.graders, {parse: true});
} }
attributes.graders = graderCollection; attributes.graders = graderCollection;
} }
// If grace period is unset or equal to 00:00 on the server, // If grace period is unset or equal to 00:00 on the server,
// it's received as null // it's received as null
if (attributes['grace_period'] === null) { if (attributes['grace_period'] === null) {
attributes.grace_period = { attributes.grace_period = {
hours: 0, hours: 0,
minutes: 0 minutes: 0
} };
} }
// If minimum_grade_credit is unset or equal to 0 on the server, // If minimum_grade_credit is unset or equal to 0 on the server,
// it's received as 0 // it's received as 0
if (attributes.minimum_grade_credit === null) { if (attributes.minimum_grade_credit === null) {
attributes.minimum_grade_credit = 0; attributes.minimum_grade_credit = 0;
} }
return attributes; return attributes;
}, },
gracePeriodToDate : function() { gracePeriodToDate: function() {
var newDate = new Date(); var newDate = new Date();
if (this.has('grace_period') && this.get('grace_period')['hours']) if (this.has('grace_period') && this.get('grace_period')['hours'])
newDate.setHours(this.get('grace_period')['hours']); newDate.setHours(this.get('grace_period')['hours']);
else newDate.setHours(0); else newDate.setHours(0);
if (this.has('grace_period') && this.get('grace_period')['minutes']) if (this.has('grace_period') && this.get('grace_period')['minutes'])
newDate.setMinutes(this.get('grace_period')['minutes']); newDate.setMinutes(this.get('grace_period')['minutes']);
else newDate.setMinutes(0); else newDate.setMinutes(0);
if (this.has('grace_period') && this.get('grace_period')['seconds']) if (this.has('grace_period') && this.get('grace_period')['seconds'])
newDate.setSeconds(this.get('grace_period')['seconds']); newDate.setSeconds(this.get('grace_period')['seconds']);
else newDate.setSeconds(0); else newDate.setSeconds(0);
return newDate; return newDate;
}, },
parseGracePeriod : function(grace_period) { parseGracePeriod: function(grace_period) {
// Enforce hours:minutes format // Enforce hours:minutes format
if(!/^\d{2,3}:\d{2}$/.test(grace_period)) { if (!/^\d{2,3}:\d{2}$/.test(grace_period)) {
return null; return null;
} }
var pieces = grace_period.split(/:/); var pieces = grace_period.split(/:/);
return {
hours: parseInt(pieces[0], 10),
minutes: parseInt(pieces[1], 10)
}
},
parseMinimumGradeCredit : function(minimum_grade_credit) {
// get the value of minimum grade credit value in percentage
if (isNaN(minimum_grade_credit)) {
return 0;
}
return parseInt(minimum_grade_credit);
},
validate : function(attrs) {
if(_.has(attrs, 'grace_period')) {
if(attrs['grace_period'] === null) {
return { return {
'grace_period': gettext('Grace period must be specified in HH:MM format.') hours: parseInt(pieces[0], 10),
minutes: parseInt(pieces[1], 10)
};
},
parseMinimumGradeCredit: function(minimum_grade_credit) {
// get the value of minimum grade credit value in percentage
if (isNaN(minimum_grade_credit)) {
return 0;
} }
} return parseInt(minimum_grade_credit);
} },
if(this.get('is_credit_course') && _.has(attrs, 'minimum_grade_credit')) { validate: function(attrs) {
if (_.has(attrs, 'grace_period')) {
if (attrs['grace_period'] === null) {
return {
'grace_period': gettext('Grace period must be specified in HH:MM format.')
};
}
}
if (this.get('is_credit_course') && _.has(attrs, 'minimum_grade_credit')) {
// Getting minimum grade cutoff value // Getting minimum grade cutoff value
var minimum_grade_cutoff = _.min(_.values(attrs.grade_cutoffs)); var minimum_grade_cutoff = _.min(_.values(attrs.grade_cutoffs));
if(isNaN(attrs.minimum_grade_credit) || attrs.minimum_grade_credit === null || attrs.minimum_grade_credit < minimum_grade_cutoff) { if (isNaN(attrs.minimum_grade_credit) || attrs.minimum_grade_credit === null || attrs.minimum_grade_credit < minimum_grade_cutoff) {
return { return {
'minimum_grade_credit': interpolate( 'minimum_grade_credit': interpolate(
gettext('Not able to set passing grade to less than %(minimum_grade_cutoff)s%.'), gettext('Not able to set passing grade to less than %(minimum_grade_cutoff)s%.'),
{minimum_grade_cutoff: minimum_grade_cutoff * 100}, {minimum_grade_cutoff: minimum_grade_cutoff * 100},
true true
) )
}; };
}
}
} }
} });
}
});
return CourseGradingPolicy; return CourseGradingPolicy;
}); // end define() }); // end define()
define(["backbone", "underscore", "gettext", "js/models/chapter", "js/collections/chapter", define(['backbone', 'underscore', 'gettext', 'js/models/chapter', 'js/collections/chapter',
"backbone.associations", "cms/js/main"], 'backbone.associations', 'cms/js/main'],
function(Backbone, _, gettext, ChapterModel, ChapterCollection) { function(Backbone, _, gettext, ChapterModel, ChapterCollection) {
var Textbook = Backbone.AssociatedModel.extend({
var Textbook = Backbone.AssociatedModel.extend({ defaults: function() {
defaults: function() {
return {
name: "",
chapters: new ChapterCollection([{}]),
showChapters: false,
editing: false
};
},
relations: [{
type: Backbone.Many,
key: "chapters",
relatedModel: ChapterModel,
collectionType: ChapterCollection
}],
initialize: function() {
this.setOriginalAttributes();
return this;
},
setOriginalAttributes: function() {
this._originalAttributes = this.parse(this.toJSON());
},
reset: function() {
this.set(this._originalAttributes, {parse: true});
},
isDirty: function() {
return !_.isEqual(this._originalAttributes, this.parse(this.toJSON()));
},
isEmpty: function() {
return !this.get('name') && this.get('chapters').isEmpty();
},
urlRoot: function() { return CMS.URL.TEXTBOOKS; },
parse: function(response) {
var ret = $.extend(true, {}, response);
if("tab_title" in ret && !("name" in ret)) {
ret.name = ret.tab_title;
delete ret.tab_title;
}
if("url" in ret && !("chapters" in ret)) {
ret.chapters = {"url": ret.url};
delete ret.url;
}
_.each(ret.chapters, function(chapter, i) {
chapter.order = chapter.order || i+1;
});
return ret;
},
toJSON: function() {
return {
tab_title: this.get('name'),
chapters: this.get('chapters').toJSON()
};
},
// NOTE: validation functions should return non-internationalized error
// messages. The messages will be passed through gettext in the template.
validate: function(attrs, options) {
if (!attrs.name) {
return { return {
message: gettext("Textbook name is required"), name: '',
attributes: {name: true} chapters: new ChapterCollection([{}]),
showChapters: false,
editing: false
}; };
} },
if (attrs.chapters.length === 0) { relations: [{
type: Backbone.Many,
key: 'chapters',
relatedModel: ChapterModel,
collectionType: ChapterCollection
}],
initialize: function() {
this.setOriginalAttributes();
return this;
},
setOriginalAttributes: function() {
this._originalAttributes = this.parse(this.toJSON());
},
reset: function() {
this.set(this._originalAttributes, {parse: true});
},
isDirty: function() {
return !_.isEqual(this._originalAttributes, this.parse(this.toJSON()));
},
isEmpty: function() {
return !this.get('name') && this.get('chapters').isEmpty();
},
urlRoot: function() { return CMS.URL.TEXTBOOKS; },
parse: function(response) {
var ret = $.extend(true, {}, response);
if ('tab_title' in ret && !('name' in ret)) {
ret.name = ret.tab_title;
delete ret.tab_title;
}
if ('url' in ret && !('chapters' in ret)) {
ret.chapters = {'url': ret.url};
delete ret.url;
}
_.each(ret.chapters, function(chapter, i) {
chapter.order = chapter.order || i + 1;
});
return ret;
},
toJSON: function() {
return { return {
message: gettext("Please add at least one chapter"), tab_title: this.get('name'),
attributes: {chapters: true} chapters: this.get('chapters').toJSON()
}; };
} else { },
// validate all chapters // NOTE: validation functions should return non-internationalized error
var invalidChapters = []; // messages. The messages will be passed through gettext in the template.
attrs.chapters.each(function(chapter) { validate: function(attrs, options) {
if(!chapter.isValid()) { if (!attrs.name) {
invalidChapters.push(chapter);
}
});
if(!_.isEmpty(invalidChapters)) {
return { return {
message: gettext("All chapters must have a name and asset"), message: gettext('Textbook name is required'),
attributes: {chapters: invalidChapters} attributes: {name: true}
}; };
} }
if (attrs.chapters.length === 0) {
return {
message: gettext('Please add at least one chapter'),
attributes: {chapters: true}
};
} else {
// validate all chapters
var invalidChapters = [];
attrs.chapters.each(function(chapter) {
if (!chapter.isValid()) {
invalidChapters.push(chapter);
}
});
if (!_.isEmpty(invalidChapters)) {
return {
message: gettext('All chapters must have a name and asset'),
attributes: {chapters: invalidChapters}
};
}
}
} }
} });
return Textbook;
}); });
return Textbook;
});
define(["backbone", "underscore", "gettext"], function(Backbone, _, gettext) { define(['backbone', 'underscore', 'gettext'], function(Backbone, _, gettext) {
var FileUpload = Backbone.Model.extend({
var FileUpload = Backbone.Model.extend({ defaults: {
defaults: { 'title': '',
"title": "", 'message': '',
"message": "", 'selectedFile': null,
"selectedFile": null, 'uploading': false,
"uploading": false, 'uploadedBytes': 0,
"uploadedBytes": 0, 'totalBytes': 0,
"totalBytes": 0, 'finished': false,
"finished": false, 'mimeTypes': [],
"mimeTypes": [], 'fileFormats': []
"fileFormats": [] },
}, validate: function(attrs, options) {
validate: function(attrs, options) { if (attrs.selectedFile && !this.checkTypeValidity(attrs.selectedFile)) {
if(attrs.selectedFile && !this.checkTypeValidity(attrs.selectedFile)) { return {
return { message: _.template(gettext('Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.'))( // eslint-disable-line max-len
message: _.template(gettext('Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.'))( // eslint-disable-line max-len
this.formatValidTypes() this.formatValidTypes()
), ),
attributes: {selectedFile: true} attributes: {selectedFile: true}
}; };
} }
}, },
// Return a list of this uploader's valid file types // Return a list of this uploader's valid file types
fileTypes: function() { fileTypes: function() {
var mimeTypes = _.map( var mimeTypes = _.map(
this.attributes.mimeTypes, this.attributes.mimeTypes,
function(type) { function(type) {
return type.split('/')[1].toUpperCase(); return type.split('/')[1].toUpperCase();
} }
), ),
fileFormats = _.map( fileFormats = _.map(
this.attributes.fileFormats, this.attributes.fileFormats,
function(type) { function(type) {
return type.toUpperCase(); return type.toUpperCase();
} }
); );
return mimeTypes.concat(fileFormats); return mimeTypes.concat(fileFormats);
}, },
checkTypeValidity: function (file) { checkTypeValidity: function(file) {
var attrs = this.attributes, var attrs = this.attributes,
getRegExp = function (formats) { getRegExp = function(formats) {
// Creates regular expression like: /(?:.+)\.(jpg|png|gif)$/i // Creates regular expression like: /(?:.+)\.(jpg|png|gif)$/i
return RegExp(('(?:.+)\\.(' + formats.join('|') + ')$'), 'i'); return RegExp(('(?:.+)\\.(' + formats.join('|') + ')$'), 'i');
}; };
return (attrs.mimeTypes.length === 0 && attrs.fileFormats.length === 0) || return (attrs.mimeTypes.length === 0 && attrs.fileFormats.length === 0) ||
_.contains(attrs.mimeTypes, file.type) || _.contains(attrs.mimeTypes, file.type) ||
getRegExp(attrs.fileFormats).test(file.name); getRegExp(attrs.fileFormats).test(file.name);
}, },
// Return strings for the valid file types and extensions this // Return strings for the valid file types and extensions this
// uploader accepts, formatted as natural language // uploader accepts, formatted as natural language
formatValidTypes: function() { formatValidTypes: function() {
var attrs = this.attributes; var attrs = this.attributes;
if(attrs.mimeTypes.concat(attrs.fileFormats).length === 1) { if (attrs.mimeTypes.concat(attrs.fileFormats).length === 1) {
return { return {
fileTypes: this.fileTypes()[0], fileTypes: this.fileTypes()[0],
fileExtensions: '.' + this.fileTypes()[0].toLowerCase() fileExtensions: '.' + this.fileTypes()[0].toLowerCase()
};
}
var or = gettext('or');
var formatTypes = function(types) {
return _.template('<%= initial %> <%= or %> <%= last %>')({
initial: _.initial(types).join(', '),
or: or,
last: _.last(types)
});
}; };
} return {
var or = gettext('or'); fileTypes: formatTypes(this.fileTypes()),
var formatTypes = function(types) { fileExtensions: formatTypes(
return _.template('<%= initial %> <%= or %> <%= last %>')({
initial: _.initial(types).join(', '),
or: or,
last: _.last(types)
});
};
return {
fileTypes: formatTypes(this.fileTypes()),
fileExtensions: formatTypes(
_.map(this.fileTypes(), _.map(this.fileTypes(),
function(type) { function(type) {
return '.' + type.toLowerCase(); return '.' + type.toLowerCase();
}) })
) )
}; };
} }
}); });
return FileUpload; return FileUpload;
}); // end define() }); // end define()
/** /**
* Provide helper methods for modal validation. * Provide helper methods for modal validation.
*/ */
define(["jquery"], define(['jquery'],
function($) { function($) {
var validateIntegerRange = function(attributeVal, range) { var validateIntegerRange = function(attributeVal, range) {
//Validating attribute should have an integer value and should be under the given range. // Validating attribute should have an integer value and should be under the given range.
var isIntegerUnderRange = true; var isIntegerUnderRange = true;
var value = Math.round(attributeVal); // see if this ensures value saved is int var value = Math.round(attributeVal); // see if this ensures value saved is int
if (!isFinite(value) || /\D+/.test(attributeVal) || value < range.min || value > range.max) { if (!isFinite(value) || /\D+/.test(attributeVal) || value < range.min || value > range.max) {
isIntegerUnderRange = false; isIntegerUnderRange = false;
} }
return isIntegerUnderRange; return isIntegerUnderRange;
} };
return { return {
'validateIntegerRange': validateIntegerRange 'validateIntegerRange': validateIntegerRange
} };
}); });
define(["js/models/custom_sync_xblock_info"], define(['js/models/custom_sync_xblock_info'],
function(CustomSyncXBlockInfo) { function(CustomSyncXBlockInfo) {
var XBlockContainerInfo = CustomSyncXBlockInfo.extend({ var XBlockContainerInfo = CustomSyncXBlockInfo.extend({
urlRoots: { urlRoots: {
......
...@@ -13,7 +13,7 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -13,7 +13,7 @@ function(Backbone, _, str, ModuleUtils) {
'display_name': null, 'display_name': null,
'category': null, 'category': null,
'data': null, 'data': null,
'metadata' : null, 'metadata': null,
/** /**
* The Studio URL for this xblock, or null if it doesn't have one. * The Studio URL for this xblock, or null if it doesn't have one.
*/ */
...@@ -30,16 +30,16 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -30,16 +30,16 @@ function(Backbone, _, str, ModuleUtils) {
/** /**
* Date of the last edit to this xblock or any of its descendants. * Date of the last edit to this xblock or any of its descendants.
*/ */
'edited_on':null, 'edited_on': null,
/** /**
* User who last edited the xblock or any of its descendants. Will only be present if * User who last edited the xblock or any of its descendants. Will only be present if
* publishing info was explicitly requested. * publishing info was explicitly requested.
*/ */
'edited_by':null, 'edited_by': null,
/** /**
* True iff a published version of the xblock exists. * True iff a published version of the xblock exists.
*/ */
"published": null, 'published': null,
/** /**
* Date of the last publish of this xblock, or null if never published. * Date of the last publish of this xblock, or null if never published.
*/ */
...@@ -54,12 +54,12 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -54,12 +54,12 @@ function(Backbone, _, str, ModuleUtils) {
* Note: this is not always provided as a performance optimization. It is only provided for * Note: this is not always provided as a performance optimization. It is only provided for
* verticals functioning as units. * verticals functioning as units.
*/ */
"has_changes": null, 'has_changes': null,
/** /**
* Represents the possible publish states for an xblock. See the documentation * Represents the possible publish states for an xblock. See the documentation
* for XBlockVisibility to see a comprehensive enumeration of the states. * for XBlockVisibility to see a comprehensive enumeration of the states.
*/ */
"visibility_state": null, 'visibility_state': null,
/** /**
* True if the release date of the xblock is in the past. * True if the release date of the xblock is in the past.
*/ */
...@@ -75,7 +75,7 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -75,7 +75,7 @@ function(Backbone, _, str, ModuleUtils) {
* This can be null if the release date is unscheduled. Will only be present if * This can be null if the release date is unscheduled. Will only be present if
* publishing info was explicitly requested. * publishing info was explicitly requested.
*/ */
'release_date_from':null, 'release_date_from': null,
/** /**
* True if this xblock is currently visible to students. This is computed server-side * True if this xblock is currently visible to students. This is computed server-side
* so that the logic isn't duplicated on the client. Will only be present if * so that the logic isn't duplicated on the client. Will only be present if
...@@ -149,16 +149,16 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -149,16 +149,16 @@ function(Backbone, _, str, ModuleUtils) {
* The XBlock's group access rules. This is a dictionary keyed to user partition IDs, * The XBlock's group access rules. This is a dictionary keyed to user partition IDs,
* where the values are lists of group IDs. * where the values are lists of group IDs.
*/ */
'group_access': null, 'group_access': null,
/** /**
* User partition dictionary. This is pre-processed by Studio, so it contains * User partition dictionary. This is pre-processed by Studio, so it contains
* some additional fields that are not stored in the course descriptor * some additional fields that are not stored in the course descriptor
* (for example, which groups are selected for this particular XBlock). * (for example, which groups are selected for this particular XBlock).
*/ */
'user_partitions': null, 'user_partitions': null
}, },
initialize: function () { initialize: function() {
// Extend our Model by helper methods. // Extend our Model by helper methods.
_.extend(this, this.getCategoryHelpers()); _.extend(this, this.getCategoryHelpers());
}, },
...@@ -180,7 +180,7 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -180,7 +180,7 @@ function(Backbone, _, str, ModuleUtils) {
}, },
createChild: function(response) { createChild: function(response) {
return new XBlockInfo(response, { parse: true }); return new XBlockInfo(response, {parse: true});
}, },
hasChildren: function() { hasChildren: function() {
...@@ -188,7 +188,7 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -188,7 +188,7 @@ function(Backbone, _, str, ModuleUtils) {
return childInfo && childInfo.children.length > 0; return childInfo && childInfo.children.length > 0;
}, },
isPublishable: function(){ isPublishable: function() {
return !this.get('published') || this.get('has_changes'); return !this.get('published') || this.get('has_changes');
}, },
...@@ -200,13 +200,13 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -200,13 +200,13 @@ function(Backbone, _, str, ModuleUtils) {
return this.isActionRequired('draggable'); return this.isActionRequired('draggable');
}, },
isChildAddable: function(){ isChildAddable: function() {
return this.isActionRequired('childAddable'); return this.isActionRequired('childAddable');
}, },
isHeaderVisible: function(){ isHeaderVisible: function() {
if(this.get('is_header_visible') !== null) { if (this.get('is_header_visible') !== null) {
return this.get('is_header_visible'); return this.get('is_header_visible');
} }
return true; return true;
}, },
...@@ -217,7 +217,7 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -217,7 +217,7 @@ function(Backbone, _, str, ModuleUtils) {
*/ */
isActionRequired: function(actionName) { isActionRequired: function(actionName) {
var actions = this.get('actions'); var actions = this.get('actions');
if(actions !== null) { if (actions !== null) {
if (_.has(actions, actionName) && !actions[actionName]) { if (_.has(actions, actionName) && !actions[actionName]) {
return false; return false;
} }
...@@ -229,26 +229,26 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -229,26 +229,26 @@ function(Backbone, _, str, ModuleUtils) {
* Return a list of convenience methods to check affiliation to the category. * Return a list of convenience methods to check affiliation to the category.
* @return {Array} * @return {Array}
*/ */
getCategoryHelpers: function () { getCategoryHelpers: function() {
var categories = ['course', 'chapter', 'sequential', 'vertical'], var categories = ['course', 'chapter', 'sequential', 'vertical'],
helpers = {}; helpers = {};
_.each(categories, function (item) { _.each(categories, function(item) {
helpers['is' + str.titleize(item)] = function () { helpers['is' + str.titleize(item)] = function() {
return this.get('category') === item; return this.get('category') === item;
}; };
}, this); }, this);
return helpers; return helpers;
}, },
/** /**
* Check if we can edit current XBlock or not on Course Outline page. * Check if we can edit current XBlock or not on Course Outline page.
* @return {Boolean} * @return {Boolean}
*/ */
isEditableOnCourseOutline: function() { isEditableOnCourseOutline: function() {
return this.isSequential() || this.isChapter() || this.isVertical(); return this.isSequential() || this.isChapter() || this.isVertical();
}, },
/* /*
* Check whether any verification checkpoints are defined in the course. * Check whether any verification checkpoints are defined in the course.
...@@ -256,10 +256,10 @@ function(Backbone, _, str, ModuleUtils) { ...@@ -256,10 +256,10 @@ function(Backbone, _, str, ModuleUtils) {
* that uses the verification partition scheme. * that uses the verification partition scheme.
*/ */
hasVerifiedCheckpoints: function() { hasVerifiedCheckpoints: function() {
var partitions = this.get("user_partitions") || []; var partitions = this.get('user_partitions') || [];
return Boolean(_.find(partitions, function(p) { return Boolean(_.find(partitions, function(p) {
return p.scheme === "verification"; return p.scheme === 'verification';
})); }));
} }
}); });
......
define(["js/models/custom_sync_xblock_info"], define(['js/models/custom_sync_xblock_info'],
function(CustomSyncXBlockInfo) { function(CustomSyncXBlockInfo) {
var XBlockOutlineInfo = CustomSyncXBlockInfo.extend({ var XBlockOutlineInfo = CustomSyncXBlockInfo.extend({
...@@ -7,7 +7,7 @@ define(["js/models/custom_sync_xblock_info"], ...@@ -7,7 +7,7 @@ define(["js/models/custom_sync_xblock_info"],
}, },
createChild: function(response) { createChild: function(response) {
return new XBlockOutlineInfo(response, { parse: true }); return new XBlockOutlineInfo(response, {parse: true});
} }
}); });
return XBlockOutlineInfo; return XBlockOutlineInfo;
......
define(["backbone", "gettext", "underscore"], function (Backbone, gettext, _) { define(['backbone', 'gettext', 'underscore'], function(Backbone, gettext, _) {
/** /**
* Model for xblock validation messages as displayed in Studio. * Model for xblock validation messages as displayed in Studio.
*/ */
...@@ -10,21 +10,21 @@ define(["backbone", "gettext", "underscore"], function (Backbone, gettext, _) { ...@@ -10,21 +10,21 @@ define(["backbone", "gettext", "underscore"], function (Backbone, gettext, _) {
xblock_id: null xblock_id: null
}, },
WARNING : "warning", WARNING: 'warning',
ERROR: "error", ERROR: 'error',
NOT_CONFIGURED: "not-configured", NOT_CONFIGURED: 'not-configured',
parse: function(response) { parse: function(response) {
if (!response.empty) { if (!response.empty) {
var summary = "summary" in response ? response.summary : {}; var summary = 'summary' in response ? response.summary : {};
var messages = "messages" in response ? response.messages : []; var messages = 'messages' in response ? response.messages : [];
if (!summary.text) { if (!summary.text) {
summary.text = gettext("This component has validation issues."); summary.text = gettext('This component has validation issues.');
} }
if (!summary.type) { if (!summary.type) {
summary.type = this.WARNING; summary.type = this.WARNING;
// Possible types are ERROR, WARNING, and NOT_CONFIGURED. NOT_CONFIGURED is treated as a warning. // Possible types are ERROR, WARNING, and NOT_CONFIGURED. NOT_CONFIGURED is treated as a warning.
_.find(messages, function (message) { _.find(messages, function(message) {
if (message.type === this.ERROR) { if (message.type === this.ERROR) {
summary.type = this.ERROR; summary.type = this.ERROR;
return true; return true;
......
define([ define([
'backbone', 'backbone',
'js/programs/utils/auth_utils' 'js/programs/utils/auth_utils'
], ],
function( Backbone, auth ) { function(Backbone, auth) {
'use strict'; 'use strict';
return Backbone.Collection.extend(auth.autoSync); return Backbone.Collection.extend(auth.autoSync);
......
define([ define([
'backbone', 'backbone',
'jquery', 'jquery',
'js/programs/utils/api_config', 'js/programs/utils/api_config',
'js/programs/collections/auto_auth_collection', 'js/programs/collections/auto_auth_collection',
'jquery.cookie' 'jquery.cookie'
], ],
function( Backbone, $, apiConfig, AutoAuthCollection ) { function(Backbone, $, apiConfig, AutoAuthCollection) {
'use strict'; 'use strict';
return AutoAuthCollection.extend({ return AutoAuthCollection.extend({
...@@ -43,7 +43,7 @@ define([ ...@@ -43,7 +43,7 @@ define([
// Adds a run back into the model for selection // Adds a run back into the model for selection
addRun: function(id) { addRun: function(id) {
var courseRun = _.findWhere( this.allRuns, { id: id }); var courseRun = _.findWhere(this.allRuns, {id: id});
this.create(courseRun); this.create(courseRun);
}, },
......
define([ define([
'backbone', 'backbone',
'jquery', 'jquery',
'js/programs/models/program_model' 'js/programs/models/program_model'
], ],
function( Backbone, $, ProgramModel ) { function(Backbone, $, ProgramModel) {
'use strict'; 'use strict';
return Backbone.Collection.extend({ return Backbone.Collection.extend({
......
define([ define([
'backbone' 'backbone'
], ],
function( Backbone ) { function(Backbone) {
'use strict'; 'use strict';
return Backbone.Model.extend({ return Backbone.Model.extend({
......
define([ define([
'backbone', 'backbone',
'js/programs/utils/auth_utils' 'js/programs/utils/auth_utils'
], ],
function( Backbone, auth ) { function(Backbone, auth) {
'use strict'; 'use strict';
return Backbone.Model.extend(auth.autoSync); return Backbone.Model.extend(auth.autoSync);
......
define([ define([
'backbone', 'backbone',
'jquery', 'jquery',
'js/programs/utils/api_config', 'js/programs/utils/api_config',
'js/programs/models/auto_auth_model', 'js/programs/models/auto_auth_model',
'jquery.cookie', 'jquery.cookie',
'gettext' 'gettext'
], ],
function( Backbone, $, apiConfig, AutoAuthModel ) { function(Backbone, $, apiConfig, AutoAuthModel) {
'use strict'; 'use strict';
return AutoAuthModel.extend({ return AutoAuthModel.extend({
......
define([ define([
'backbone' 'backbone'
], ],
function( Backbone ) { function(Backbone) {
'use strict'; 'use strict';
return Backbone.Model.extend({ return Backbone.Model.extend({
......
define([ define([
'js/programs/utils/api_config', 'js/programs/utils/api_config',
'js/programs/models/auto_auth_model' 'js/programs/models/auto_auth_model'
], ],
function( apiConfig, AutoAuthModel ) { function(apiConfig, AutoAuthModel) {
'use strict'; 'use strict';
return AutoAuthModel.extend({ return AutoAuthModel.extend({
......
define([ define([
'backbone', 'backbone',
'jquery', 'jquery',
'js/programs/utils/api_config', 'js/programs/utils/api_config',
'js/programs/models/auto_auth_model', 'js/programs/models/auto_auth_model',
'gettext', 'gettext',
'jquery.cookie' 'jquery.cookie'
], ],
function( Backbone, $, apiConfig, AutoAuthModel, gettext ) { function(Backbone, $, apiConfig, AutoAuthModel, gettext) {
'use strict'; 'use strict';
return AutoAuthModel.extend({ return AutoAuthModel.extend({
...@@ -37,7 +37,7 @@ define([ ...@@ -37,7 +37,7 @@ define([
this.url = apiConfig.get('programsApiUrl') + 'programs/' + this.id + '/'; this.url = apiConfig.get('programsApiUrl') + 'programs/' + this.id + '/';
}, },
validateOrganizations: function( orgArray ) { validateOrganizations: function(orgArray) {
/** /**
* The array passed to this method contains a single object representing * The array passed to this method contains a single object representing
* the selected organization; the object contains the organization's key. * the selected organization; the object contains the organization's key.
...@@ -46,61 +46,61 @@ define([ ...@@ -46,61 +46,61 @@ define([
var i, var i,
len = orgArray ? orgArray.length : 0; len = orgArray ? orgArray.length : 0;
for ( i = 0; i < len; i++ ) { for (i = 0; i < len; i++) {
if ( orgArray[i].key === 'false' ) { if (orgArray[i].key === 'false') {
return gettext('Please select a valid organization.'); return gettext('Please select a valid organization.');
} }
} }
}, },
getConfig: function( options ) { getConfig: function(options) {
var patch = options && options.patch, var patch = options && options.patch,
params = patch ? this.get('id') + '/' : '', params = patch ? this.get('id') + '/' : '',
config = _.extend({ validate: true, parse: true }, { config = _.extend({validate: true, parse: true}, {
type: patch ? 'PATCH' : 'POST', type: patch ? 'PATCH' : 'POST',
url: apiConfig.get('programsApiUrl') + 'programs/' + params, url: apiConfig.get('programsApiUrl') + 'programs/' + params,
contentType: patch ? 'application/merge-patch+json' : 'application/json', contentType: patch ? 'application/merge-patch+json' : 'application/json',
context: this, context: this,
// NB: setting context fails in tests // NB: setting context fails in tests
success: _.bind( this.saveSuccess, this ), success: _.bind(this.saveSuccess, this),
error: _.bind( this.saveError, this ) error: _.bind(this.saveError, this)
}); });
if ( patch ) { if (patch) {
config.data = JSON.stringify( options.update ) || this.attributes; config.data = JSON.stringify(options.update) || this.attributes;
} }
return config; return config;
}, },
patch: function( data ) { patch: function(data) {
this.save({ this.save({
patch: true, patch: true,
update: data update: data
}); });
}, },
save: function( options ) { save: function(options) {
var method, var method,
patch = options && options.patch ? true : false, patch = options && options.patch ? true : false,
config = this.getConfig( options ); config = this.getConfig(options);
/** /**
* Simplified version of code from the default Backbone save function * Simplified version of code from the default Backbone save function
* http://backbonejs.org/docs/backbone.html#section-87 * http://backbonejs.org/docs/backbone.html#section-87
*/ */
method = this.isNew() ? 'create' : ( patch ? 'patch' : 'update' ); method = this.isNew() ? 'create' : (patch ? 'patch' : 'update');
this.sync( method, this, config ); this.sync(method, this, config);
}, },
saveError: function( jqXHR ) { saveError: function(jqXHR) {
this.trigger( 'error', jqXHR ); this.trigger('error', jqXHR);
}, },
saveSuccess: function( data ) { saveSuccess: function(data) {
this.set({ id: data.id }); this.set({id: data.id});
this.trigger( 'sync', this ); this.trigger('sync', this);
} }
}); });
} }
......
(function() { (function() {
'use strict'; 'use strict';
require([ require([
'js/programs/views/program_admin_app_view' 'js/programs/views/program_admin_app_view'
], ],
function( ProgramAdminAppView ) { function(ProgramAdminAppView) {
return new ProgramAdminAppView(); return new ProgramAdminAppView();
} }
); );
......
define([ define([
'backbone', 'backbone',
'js/programs/views/program_creator_view', 'js/programs/views/program_creator_view',
'js/programs/views/program_details_view', 'js/programs/views/program_details_view',
'js/programs/models/program_model' 'js/programs/models/program_model'
], ],
function( Backbone, ProgramCreatorView, ProgramDetailsView, ProgramModel ) { function(Backbone, ProgramCreatorView, ProgramDetailsView, ProgramModel) {
'use strict'; 'use strict';
return Backbone.Router.extend({ return Backbone.Router.extend({
...@@ -15,7 +15,7 @@ define([ ...@@ -15,7 +15,7 @@ define([
':id': 'programDetails' ':id': 'programDetails'
}, },
initialize: function( options ) { initialize: function(options) {
this.homeUrl = options.homeUrl; this.homeUrl = options.homeUrl;
}, },
...@@ -30,7 +30,7 @@ define([ ...@@ -30,7 +30,7 @@ define([
}, },
programCreator: function() { programCreator: function() {
if ( this.programCreatorView ) { if (this.programCreatorView) {
this.programCreatorView.destroy(); this.programCreatorView.destroy();
} }
...@@ -39,20 +39,20 @@ define([ ...@@ -39,20 +39,20 @@ define([
}); });
}, },
programDetails: function( id ) { programDetails: function(id) {
this.programModel = new ProgramModel({ this.programModel = new ProgramModel({
id: id id: id
}); });
this.programModel.on( 'sync', this.loadProgramDetails, this ); this.programModel.on('sync', this.loadProgramDetails, this);
this.programModel.fetch(); this.programModel.fetch();
}, },
/** /**
* Starts the router. * Starts the router.
*/ */
start: function () { start: function() {
if ( !Backbone.history.started ) { if (!Backbone.history.started) {
Backbone.history.start({ Backbone.history.start({
pushState: true, pushState: true,
root: this.root root: this.root
......
...@@ -6,14 +6,14 @@ ...@@ -6,14 +6,14 @@
(function() { (function() {
'use strict'; 'use strict';
if ( !window.gettext ) { if (!window.gettext) {
window.gettext = function (text) { window.gettext = function(text) {
return text; return text;
}; };
} }
if ( !window.interpolate ) { if (!window.interpolate) {
window.interpolate = function (text) { window.interpolate = function(text) {
return text; return text;
}; };
} }
......
define([ define([
'js/programs/models/api_config_model' 'js/programs/models/api_config_model'
], ],
function( ApiConfigModel ) { function(ApiConfigModel) {
'use strict'; 'use strict';
/** /**
...@@ -16,6 +16,5 @@ define([ ...@@ -16,6 +16,5 @@ define([
} }
return instance; return instance;
} }
); );
define([ define([
'jquery', 'jquery',
'underscore', 'underscore',
'js/programs/utils/api_config' 'js/programs/utils/api_config'
], ],
function( $, _, apiConfig ) { function($, _, apiConfig) {
'use strict'; 'use strict';
var auth = { var auth = {
...@@ -20,11 +20,10 @@ define([ ...@@ -20,11 +20,10 @@ define([
* implementation. * implementation.
* *
*/ */
sync: function( method, model, options ) { sync: function(method, model, options) {
var oldError = options.error; var oldError = options.error;
this._setHeaders( options ); this._setHeaders(options);
options.notifyOnError = false; // suppress Studio error pop-up that will happen if we get a 401 options.notifyOnError = false; // suppress Studio error pop-up that will happen if we get a 401
...@@ -38,7 +37,7 @@ define([ ...@@ -38,7 +37,7 @@ define([
delete options.xhr; // remove the failed (401) xhr from the last try. delete options.xhr; // remove the failed (401) xhr from the last try.
// update authorization header // update authorization header
this._setHeaders( options ); this._setHeaders(options);
Backbone.sync.call(this, method, model, options); Backbone.sync.call(this, method, model, options);
}.bind(this)); }.bind(this));
...@@ -54,11 +53,11 @@ define([ ...@@ -54,11 +53,11 @@ define([
* Fix up headers on an imminent AJAX sync, ensuring that the JWT token is enclosed * Fix up headers on an imminent AJAX sync, ensuring that the JWT token is enclosed
* and that credentials are included when the request is being made cross-domain. * and that credentials are included when the request is being made cross-domain.
*/ */
_setHeaders: function( ajaxOptions ) { _setHeaders: function(ajaxOptions) {
ajaxOptions.headers = _.extend ( ajaxOptions.headers || {}, { ajaxOptions.headers = _.extend(ajaxOptions.headers || {}, {
Authorization: 'JWT ' + apiConfig.get( 'idToken' ) Authorization: 'JWT ' + apiConfig.get('idToken')
}); });
ajaxOptions.xhrFields = _.extend( ajaxOptions.xhrFields || {}, { ajaxOptions.xhrFields = _.extend(ajaxOptions.xhrFields || {}, {
withCredentials: true withCredentials: true
}); });
}, },
...@@ -67,8 +66,7 @@ define([ ...@@ -67,8 +66,7 @@ define([
* Fetch a new id token from the configured endpoint, update the api config, * Fetch a new id token from the configured endpoint, update the api config,
* and invoke the specified callback. * and invoke the specified callback.
*/ */
_updateToken: function( success ) { _updateToken: function(success) {
$.ajax({ $.ajax({
url: apiConfig.get('authUrl'), url: apiConfig.get('authUrl'),
xhrFields: { xhrFields: {
...@@ -76,10 +74,10 @@ define([ ...@@ -76,10 +74,10 @@ define([
withCredentials: true withCredentials: true
}, },
crossDomain: true crossDomain: true
}).done(function ( data ) { }).done(function(data) {
// save the newly-retrieved id token // save the newly-retrieved id token
apiConfig.set( 'idToken', data.id_token ); apiConfig.set('idToken', data.id_token);
}).done( success ); }).done(success);
} }
} }
}; };
......
define([ define([
'backbone', 'backbone',
'backbone.validation', 'backbone.validation',
'underscore', 'underscore',
'gettext' 'gettext'
], ],
function( Backbone, BackboneValidation, _, gettext ) { function(Backbone, BackboneValidation, _, gettext) {
'use strict'; 'use strict';
var errorClass = 'has-error', var errorClass = 'has-error',
...@@ -14,52 +14,52 @@ define([ ...@@ -14,52 +14,52 @@ define([
// These are the same messages provided by Backbone.Validation, // These are the same messages provided by Backbone.Validation,
// marked for translation. // marked for translation.
// See: http://thedersen.com/projects/backbone-validation/#overriding-the-default-error-messages. // See: http://thedersen.com/projects/backbone-validation/#overriding-the-default-error-messages.
_.extend( Backbone.Validation.messages, { _.extend(Backbone.Validation.messages, {
required: gettext( '{0} is required' ), required: gettext('{0} is required'),
acceptance: gettext( '{0} must be accepted' ), acceptance: gettext('{0} must be accepted'),
min: gettext( '{0} must be greater than or equal to {1}' ), min: gettext('{0} must be greater than or equal to {1}'),
max: gettext( '{0} must be less than or equal to {1}' ), max: gettext('{0} must be less than or equal to {1}'),
range: gettext( '{0} must be between {1} and {2}' ), range: gettext('{0} must be between {1} and {2}'),
length: gettext( '{0} must be {1} characters' ), length: gettext('{0} must be {1} characters'),
minLength: gettext( '{0} must be at least {1} characters' ), minLength: gettext('{0} must be at least {1} characters'),
maxLength: gettext( '{0} must be at most {1} characters' ), maxLength: gettext('{0} must be at most {1} characters'),
rangeLength: gettext( '{0} must be between {1} and {2} characters' ), rangeLength: gettext('{0} must be between {1} and {2} characters'),
oneOf: gettext( '{0} must be one of: {1}' ), oneOf: gettext('{0} must be one of: {1}'),
equalTo: gettext( '{0} must be the same as {1}' ), equalTo: gettext('{0} must be the same as {1}'),
digits: gettext( '{0} must only contain digits' ), digits: gettext('{0} must only contain digits'),
number: gettext( '{0} must be a number' ), number: gettext('{0} must be a number'),
email: gettext( '{0} must be a valid email' ), email: gettext('{0} must be a valid email'),
url: gettext( '{0} must be a valid url' ), url: gettext('{0} must be a valid url'),
inlinePattern: gettext( '{0} is invalid' ) inlinePattern: gettext('{0} is invalid')
}); });
_.extend( Backbone.Validation.callbacks, { _.extend(Backbone.Validation.callbacks, {
// Gets called when a previously invalid field in the // Gets called when a previously invalid field in the
// view becomes valid. Removes any error message. // view becomes valid. Removes any error message.
valid: function( view, attr, selector ) { valid: function(view, attr, selector) {
var $input = view.$( '[' + selector + '~="' + attr + '"]' ), var $input = view.$('[' + selector + '~="' + attr + '"]'),
$message = $input.siblings( messageEl ); $message = $input.siblings(messageEl);
$input.removeClass( errorClass ) $input.removeClass(errorClass)
.removeAttr( 'data-error' ); .removeAttr('data-error');
$message.removeClass( errorClass ) $message.removeClass(errorClass)
.find( messageContent ) .find(messageContent)
.text( '' ); .text('');
}, },
// Gets called when a field in the view becomes invalid. // Gets called when a field in the view becomes invalid.
// Adds a error message. // Adds a error message.
invalid: function( view, attr, error, selector ) { invalid: function(view, attr, error, selector) {
var $input = view.$( '[' + selector + '~="' + attr + '"]' ), var $input = view.$('[' + selector + '~="' + attr + '"]'),
$message = $input.siblings( messageEl ); $message = $input.siblings(messageEl);
$input.addClass( errorClass ) $input.addClass(errorClass)
.attr( 'data-error', error ); .attr('data-error', error);
$message.addClass( errorClass ) $message.addClass(errorClass)
.find( messageContent ) .find(messageContent)
.text( $input.data('error') ); .text($input.data('error'));
} }
}); });
......
define([ define([
'backbone', 'backbone',
'jquery', 'jquery',
'underscore', 'underscore',
'js/programs/utils/constants', 'js/programs/utils/constants',
'text!templates/programs/confirm_modal.underscore', 'text!templates/programs/confirm_modal.underscore',
'edx-ui-toolkit/js/utils/html-utils', 'edx-ui-toolkit/js/utils/html-utils',
'gettext' 'gettext'
], ],
function( Backbone, $, _, constants, ModalTpl, HtmlUtils ) { function(Backbone, $, _, constants, ModalTpl, HtmlUtils) {
'use strict'; 'use strict';
return Backbone.View.extend({ return Backbone.View.extend({
...@@ -17,17 +17,17 @@ define([ ...@@ -17,17 +17,17 @@ define([
'keydown': 'handleKeydown' 'keydown': 'handleKeydown'
}, },
tpl: HtmlUtils.template( ModalTpl ), tpl: HtmlUtils.template(ModalTpl),
initialize: function( options ) { initialize: function(options) {
this.$parentEl = $( options.parentEl ); this.$parentEl = $(options.parentEl);
this.callback = options.callback; this.callback = options.callback;
this.content = options.content; this.content = options.content;
this.render(); this.render();
}, },
render: function() { render: function() {
HtmlUtils.setHtml(this.$el, this.tpl( this.content )); HtmlUtils.setHtml(this.$el, this.tpl(this.content));
HtmlUtils.setHtml(this.$parentEl, HtmlUtils.HTML(this.$el)); HtmlUtils.setHtml(this.$parentEl, HtmlUtils.HTML(this.$el));
this.postRender(); this.postRender();
}, },
...@@ -47,10 +47,10 @@ define([ ...@@ -47,10 +47,10 @@ define([
this.$parentEl.html(''); this.$parentEl.html('');
}, },
handleKeydown: function( event ) { handleKeydown: function(event) {
var keyCode = event.keyCode; var keyCode = event.keyCode;
if ( keyCode === constants.keyCodes.esc ) { if (keyCode === constants.keyCodes.esc) {
this.destroy(); this.destroy();
} }
} }
......
define([ define([
'backbone', 'backbone',
'backbone.validation', 'backbone.validation',
'jquery', 'jquery',
'underscore', 'underscore',
'js/programs/models/course_model', 'js/programs/models/course_model',
'js/programs/models/course_run_model', 'js/programs/models/course_run_model',
'js/programs/models/program_model', 'js/programs/models/program_model',
'js/programs/views/course_run_view', 'js/programs/views/course_run_view',
'text!templates/programs/course_details.underscore', 'text!templates/programs/course_details.underscore',
'edx-ui-toolkit/js/utils/html-utils', 'edx-ui-toolkit/js/utils/html-utils',
'gettext', 'gettext',
'js/programs/utils/validation_config' 'js/programs/utils/validation_config'
], ],
function( Backbone, BackboneValidation, $, _, CourseModel, CourseRunModel, function(Backbone, BackboneValidation, $, _, CourseModel, CourseRunModel,
ProgramModel, CourseRunView, ListTpl, HtmlUtils ) { ProgramModel, CourseRunView, ListTpl, HtmlUtils) {
'use strict'; 'use strict';
return Backbone.View.extend({ return Backbone.View.extend({
...@@ -27,19 +27,19 @@ define([ ...@@ -27,19 +27,19 @@ define([
'click .js-add-course-run': 'addCourseRun' 'click .js-add-course-run': 'addCourseRun'
}, },
tpl: HtmlUtils.template( ListTpl ), tpl: HtmlUtils.template(ListTpl),
initialize: function( options ) { initialize: function(options) {
this.model = new CourseModel(); this.model = new CourseModel();
Backbone.Validation.bind( this ); Backbone.Validation.bind(this);
this.$parentEl = $( this.parentEl ); this.$parentEl = $(this.parentEl);
// For managing subViews // For managing subViews
this.courseRunViews = []; this.courseRunViews = [];
this.courseRuns = options.courseRuns; this.courseRuns = options.courseRuns;
this.programModel = options.programModel; this.programModel = options.programModel;
if ( options.courseData ) { if (options.courseData) {
this.model.set(options.courseData); this.model.set(options.courseData);
} else { } else {
this.model.set({run_modes: []}); this.model.set({run_modes: []});
...@@ -53,13 +53,13 @@ define([ ...@@ -53,13 +53,13 @@ define([
render: function() { render: function() {
HtmlUtils.setHtml(this.$el, this.tpl(this.formatData())); HtmlUtils.setHtml(this.$el, this.tpl(this.formatData()));
this.$parentEl.append( this.$el ); this.$parentEl.append(this.$el);
this.postRender(); this.postRender();
}, },
postRender: function() { postRender: function() {
var runs = this.model.get('run_modes'); var runs = this.model.get('run_modes');
if ( runs && runs.length > 0 ) { if (runs && runs.length > 0) {
this.addCourseRuns(); this.addCourseRuns();
} }
}, },
...@@ -81,7 +81,7 @@ define([ ...@@ -81,7 +81,7 @@ define([
$parentEl: $runsContainer $parentEl: $runsContainer
}); });
this.courseRunViews.push( runView ); this.courseRunViews.push(runView);
}, },
addCourseRuns: function() { addCourseRuns: function() {
...@@ -89,7 +89,7 @@ define([ ...@@ -89,7 +89,7 @@ define([
var runs = this.model.get('run_modes'), var runs = this.model.get('run_modes'),
$runsContainer = this.$el.find('.js-course-runs'); $runsContainer = this.$el.find('.js-course-runs');
_.each( runs, function( run ) { _.each(runs, function(run) {
var runModel = new CourseRunModel(), var runModel = new CourseRunModel(),
runView; runView;
...@@ -103,20 +103,20 @@ define([ ...@@ -103,20 +103,20 @@ define([
$parentEl: $runsContainer $parentEl: $runsContainer
}); });
this.courseRunViews.push( runView ); this.courseRunViews.push(runView);
return runView; return runView;
}.bind(this) ); }.bind(this));
}, },
addCourseToProgram: function() { addCourseToProgram: function() {
var courseCodes = this.programModel.get('course_codes'), var courseCodes = this.programModel.get('course_codes'),
courseData = this.model.toJSON(); courseData = this.model.toJSON();
if ( this.programModel.isValid( true ) ) { if (this.programModel.isValid(true)) {
// We don't want to save the cid so omit it // We don't want to save the cid so omit it
courseCodes.push( _.omit(courseData, 'cid') ); courseCodes.push(_.omit(courseData, 'cid'));
this.programModel.patch({ course_codes: courseCodes }); this.programModel.patch({course_codes: courseCodes});
} }
}, },
// Delete this view // Delete this view
...@@ -131,16 +131,16 @@ define([ ...@@ -131,16 +131,16 @@ define([
destroyChildren: function() { destroyChildren: function() {
var runs = this.courseRunViews; var runs = this.courseRunViews;
_.each( runs, function( run ) { _.each(runs, function(run) {
run.removeRun(); run.removeRun();
}); });
}, },
// Format data to be passed to the template // Format data to be passed to the template
formatData: function() { formatData: function() {
var data = $.extend( {}, var data = $.extend({},
{ courseRuns: this.courseRuns.models }, {courseRuns: this.courseRuns.models},
_.omit( this.programModel.toJSON(), 'run_modes'), _.omit(this.programModel.toJSON(), 'run_modes'),
this.model.toJSON() this.model.toJSON()
); );
...@@ -153,14 +153,14 @@ define([ ...@@ -153,14 +153,14 @@ define([
name = this.model.get('display_name'), name = this.model.get('display_name'),
update = []; update = [];
update = _.reject( courseCodes, function(course) { update = _.reject(courseCodes, function(course) {
return course.key === key && course.display_name === name; return course.key === key && course.display_name === name;
}); });
this.programModel.patch({ course_codes: update }); this.programModel.patch({course_codes: update});
}, },
setCourse: function( event ) { setCourse: function(event) {
var $form = this.$('.js-course-form'), var $form = this.$('.js-course-form'),
title = $form.find('.display-name').val(), title = $form.find('.display-name').val(),
key = $form.find('.course-key').val(); key = $form.find('.course-key').val();
...@@ -173,7 +173,7 @@ define([ ...@@ -173,7 +173,7 @@ define([
organization: this.programModel.get('organizations')[0] organization: this.programModel.get('organizations')[0]
}); });
if ( this.model.isValid(true) ) { if (this.model.isValid(true)) {
this.addCourseToProgram(); this.addCourseToProgram();
this.updateDOM(); this.updateDOM();
this.addCourseRuns(); this.addCourseRuns();
...@@ -181,7 +181,7 @@ define([ ...@@ -181,7 +181,7 @@ define([
}, },
updateDOM: function() { updateDOM: function() {
HtmlUtils.setHtml(this.$el, this.tpl( this.formatData() ) ); HtmlUtils.setHtml(this.$el, this.tpl(this.formatData()));
}, },
updateRuns: function() { updateRuns: function() {
...@@ -190,13 +190,13 @@ define([ ...@@ -190,13 +190,13 @@ define([
name = this.model.get('display_name'), name = this.model.get('display_name'),
index; index;
if ( this.programModel.isValid( true ) ) { if (this.programModel.isValid(true)) {
index = _.findIndex( courseCodes, function(course) { index = _.findIndex(courseCodes, function(course) {
return course.key === key && course.display_name === name; return course.key === key && course.display_name === name;
}); });
courseCodes[index] = this.model.toJSON(); courseCodes[index] = this.model.toJSON();
this.programModel.patch({ course_codes: courseCodes }); this.programModel.patch({course_codes: courseCodes});
} }
} }
}); });
......
define([ define([
'backbone', 'backbone',
'jquery', 'jquery',
'underscore', 'underscore',
'text!templates/programs/course_run.underscore', 'text!templates/programs/course_run.underscore',
'edx-ui-toolkit/js/utils/html-utils' 'edx-ui-toolkit/js/utils/html-utils'
], ],
function ( Backbone, $, _, CourseRunTpl, HtmlUtils ) { function(Backbone, $, _, CourseRunTpl, HtmlUtils) {
'use strict'; 'use strict';
return Backbone.View.extend({ return Backbone.View.extend({
...@@ -14,9 +14,9 @@ define([ ...@@ -14,9 +14,9 @@ define([
'click .js-remove-run': 'removeRun' 'click .js-remove-run': 'removeRun'
}, },
tpl: HtmlUtils.template( CourseRunTpl ), tpl: HtmlUtils.template(CourseRunTpl),
initialize: function( options ) { initialize: function(options) {
/** /**
* Need the run model for the template, and the courseModel * Need the run model for the template, and the courseModel
* to keep parent view up to date with run changes * to keep parent view up to date with run changes
...@@ -37,12 +37,12 @@ define([ ...@@ -37,12 +37,12 @@ define([
data.programStatus = this.programStatus; data.programStatus = this.programStatus;
if ( !!this.courseRuns ) { if (!!this.courseRuns) {
data.courseRuns = this.courseRuns.toJSON(); data.courseRuns = this.courseRuns.toJSON();
} }
HtmlUtils.setHtml(this.$el, this.tpl( data ) ); HtmlUtils.setHtml(this.$el, this.tpl(data));
this.$parentEl.append( this.$el ); this.$parentEl.append(this.$el);
}, },
// Delete this view // Delete this view
...@@ -52,7 +52,7 @@ define([ ...@@ -52,7 +52,7 @@ define([
}, },
// Data returned from courseList API is not the correct format // Data returned from courseList API is not the correct format
formatData: function( data ) { formatData: function(data) {
return { return {
course_key: data.id, course_key: data.id,
mode_slug: 'verified', mode_slug: 'verified',
...@@ -72,7 +72,7 @@ define([ ...@@ -72,7 +72,7 @@ define([
runs = _.clone(this.courseModel.get('run_modes')), runs = _.clone(this.courseModel.get('run_modes')),
updatedRuns = []; updatedRuns = [];
updatedRuns = _.reject( runs, function( obj ) { updatedRuns = _.reject(runs, function(obj) {
return obj.start_date === startDate && return obj.start_date === startDate &&
obj.course_key === courseKey; obj.course_key === courseKey;
}); });
...@@ -96,7 +96,7 @@ define([ ...@@ -96,7 +96,7 @@ define([
runs = _.clone(this.courseModel.get('run_modes')), runs = _.clone(this.courseModel.get('run_modes')),
data = this.formatData(runObj); data = this.formatData(runObj);
this.model.set( data ); this.model.set(data);
runs.push(data); runs.push(data);
this.courseModel.set({run_modes: runs}); this.courseModel.set({run_modes: runs});
this.courseRuns.removeRun(id); this.courseRuns.removeRun(id);
...@@ -104,7 +104,7 @@ define([ ...@@ -104,7 +104,7 @@ define([
// If a run has not been selected update the dropdown options // If a run has not been selected update the dropdown options
updateDropdown: function() { updateDropdown: function() {
if ( !this.model.get('course_key') ) { if (!this.model.get('course_key')) {
this.render(); this.render();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment