diff --git a/cms/static/cms/js/spec/main.js b/cms/static/cms/js/spec/main.js
index a734ab416a94..e7660161da33 100644
--- a/cms/static/cms/js/spec/main.js
+++ b/cms/static/cms/js/spec/main.js
@@ -233,7 +233,6 @@
'js/spec/models/metadata_spec',
'js/spec/models/section_spec',
'js/spec/models/settings_course_grader_spec',
- 'js/spec/models/settings_grading_spec',
'js/spec/models/upload_spec',
'js/spec/views/metadata_edit_spec',
'js/spec/views/upload_spec',
@@ -263,8 +262,7 @@
'js/spec/views/pages/library_users_spec',
'js/spec/views/modals/base_modal_spec',
'js/spec/views/modals/move_xblock_modal_spec',
- 'js/spec/views/modals/validation_error_modal_spec',
- 'js/spec/views/settings/main_spec',
+ 'js/spec/views/modals/validation_error_modal_spec'
];
i = 0;
diff --git a/cms/static/js/collections/course_grader.js b/cms/static/js/collections/course_grader.js
deleted file mode 100644
index c7f61483635e..000000000000
--- a/cms/static/js/collections/course_grader.js
+++ /dev/null
@@ -1,10 +0,0 @@
-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);
- }
- });
-
- return CourseGraderCollection;
-}); // end define()
diff --git a/cms/static/js/models/settings/course_details.js b/cms/static/js/models/settings/course_details.js
deleted file mode 100644
index 1714436d7d32..000000000000
--- a/cms/static/js/models/settings/course_details.js
+++ /dev/null
@@ -1,165 +0,0 @@
-define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js/utils/date_utils',
- 'edx-ui-toolkit/js/utils/string-utils'
-],
-function(Backbone, _, gettext, ValidationHelpers, DateUtils, StringUtils) {
- 'use strict';
-
- var CourseDetails = Backbone.Model.extend({
- defaults: {
- org: '',
- course_id: '',
- run: '',
- language: '',
- start_date: null, // maps to 'start'
- end_date: null, // maps to 'end'
- certificates_display_behavior: '',
- certificate_available_date: null,
- 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: {},
- self_paced: null
- },
-
- validate: function(newattrs) {
- // 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.
- var errors = {};
- const CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS = {
- END: 'end',
- END_WITH_DATE: 'end_with_date',
- EARLY_NO_INFO: 'early_no_info'
- };
-
- newattrs = DateUtils.convertDateStringsToObjects(
- newattrs,
- ['start_date', 'end_date', 'certificate_available_date', 'enrollment_start', 'enrollment_end']
- );
-
- if (newattrs.start_date === null) {
- 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) {
- 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) {
- 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) {
- 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) {
- errors.enrollment_end = gettext('The enrollment end date cannot be after the course end date.');
- }
- if (this.showCertificateAvailableDate && newattrs.end_date && newattrs.certificate_available_date
- && newattrs.certificate_available_date < newattrs.end_date) {
- errors.certificate_available_date = gettext(
- 'The certificate available date must be later than the course end date.'
- );
- }
-
- if (
- newattrs.certificates_display_behavior
- && !(Object.values(CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS).includes(newattrs.certificates_display_behavior))
- ) {
- errors.certificates_display_behavior = StringUtils.interpolate(
- gettext(
- 'The certificate display behavior must be one of: {behavior_options}'
- ),
- {
- behavior_options: Object.values(CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS).join(', ')
- }
- );
- }
-
- // Throw error if there's a value for certificate_available_date
- if (
- (newattrs.certificate_available_date && newattrs.certificates_display_behavior != CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS.END_WITH_DATE)
- || (!newattrs.certificate_available_date && newattrs.certificates_display_behavior == CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS.END_WITH_DATE)
- ) {
- errors.certificates_display_behavior = StringUtils.interpolate(
- gettext(
- 'The certificates display behavior must be {valid_option} if certificate available date is set.'
- ),
- {
- valid_option: CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS.END_WITH_DATE
- }
- );
- }
-
- if (newattrs.intro_video && newattrs.intro_video !== this.get('intro_video')) {
- if (this._videokey_illegal_chars.exec(newattrs.intro_video)) {
- 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
- }
- if (_.has(newattrs, 'entrance_exam_minimum_score_pct')) {
- var range = {
- min: 1,
- max: 100
- };
- if (!ValidationHelpers.validateIntegerRange(newattrs.entrance_exam_minimum_score_pct, range)) {
- errors.entrance_exam_minimum_score_pct = StringUtils.interpolate(gettext(
- 'Please enter an integer between %(min)s and %(max)s.'
- ), range, true);
- }
- }
- if (!_.isEmpty(errors)) { return errors; }
- // NOTE don't return empty errors as that will be interpreted as an error state
- },
-
- _videokey_illegal_chars: /[^a-zA-Z0-9_-]/g,
-
- set_videosource: function(newsource) {
- // newsource either is or just the "speed:key, *" string
- // 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});
- } else {
- // TODO remove all whitespace w/in string
- if (this.get('intro_video') !== newsource) { this.set('intro_video', newsource, {validate: true}); }
- }
-
- return this.videosourceSample();
- },
-
- videosourceSample: function() {
- if (this.has('intro_video')) { return '//www.youtube.com/embed/' + this.get('intro_video'); } else { return ''; }
- },
-
- // Whether or not the course pacing can be toggled. If the course
- // has already started, returns false; otherwise, returns true.
- canTogglePace: function() {
- return new Date() <= new Date(this.get('start_date'));
- }
- });
-
- return CourseDetails;
-}); // end define()
diff --git a/cms/static/js/models/settings/course_grading_policy.js b/cms/static/js/models/settings/course_grading_policy.js
deleted file mode 100644
index 4ed105c7ee6f..000000000000
--- a/cms/static/js/models/settings/course_grading_policy.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/* globals _ */
-define(['backbone', 'js/models/location', 'js/collections/course_grader', 'edx-ui-toolkit/js/utils/string-utils'],
- function(Backbone, Location, CourseGraderCollection, StringUtils) {
- 'use strict';
-
- var CourseGradingPolicy = Backbone.Model.extend({
- defaults: {
- graders: null, // CourseGraderCollection
- grade_cutoffs: null, // CourseGradeCutoff model
- grace_period: null, // either null or { hours: n, minutes: m, ...}
- minimum_grade_credit: null, // either null or percentage
- assignment_count_info: [], // Object with keys mapping assignment type names to a list of
- // assignment display names
- },
- parse: function(attributes) {
- if (attributes.graders) {
- var graderCollection;
- // interesting race condition: if {parse:true} when newing, then parse called before .attributes created
- if (this.attributes && this.has('graders')) {
- graderCollection = this.get('graders');
- graderCollection.reset(attributes.graders, {parse: true});
- } else {
- graderCollection = new CourseGraderCollection(attributes.graders, {parse: true});
- }
- attributes.graders = graderCollection;
- }
- // If grace period is unset or equal to 00:00 on the server,
- // it's received as null
- if (attributes.grace_period === null) {
- attributes.grace_period = {
- hours: 0,
- minutes: 0
- };
- }
- // If minimum_grade_credit is unset or equal to 0 on the server,
- // it's received as 0
- if (attributes.minimum_grade_credit === null) {
- attributes.minimum_grade_credit = 0;
- }
- return attributes;
- },
- gracePeriodToDate: function() {
- var newDate = new Date();
- if (this.has('grace_period') && this.get('grace_period').hours) {
- newDate.setHours(this.get('grace_period').hours);
- } else { newDate.setHours(0); }
- if (this.has('grace_period') && this.get('grace_period').minutes) {
- newDate.setMinutes(this.get('grace_period').minutes);
- } else { newDate.setMinutes(0); }
- if (this.has('grace_period') && this.get('grace_period').seconds) {
- newDate.setSeconds(this.get('grace_period').seconds);
- } else { newDate.setSeconds(0); }
-
- return newDate;
- },
- parseGracePeriod: function(grace_period) {
- // Enforce hours:minutes format
- if (!/^\d{2,3}:\d{2}$/.test(grace_period)) {
- return null;
- }
- 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) {
- var minimumGradeCutoff;
- 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
- minimumGradeCutoff = _.min(_.values(attrs.grade_cutoffs));
- if (isNaN(attrs.minimum_grade_credit) || attrs.minimum_grade_credit === null
- || attrs.minimum_grade_credit < minimumGradeCutoff) {
- return {
- minimum_grade_credit: StringUtils.interpolate(
- gettext('Not able to set passing grade to less than %(minimum_grade_cutoff)s%.'),
- {minimum_grade_cutoff: minimumGradeCutoff * 100},
- true
- )
- };
- }
- }
- }
- });
-
- return CourseGradingPolicy;
- }); // end define()
diff --git a/cms/static/js/spec/models/settings_grading_spec.js b/cms/static/js/spec/models/settings_grading_spec.js
deleted file mode 100644
index f74e5b079736..000000000000
--- a/cms/static/js/spec/models/settings_grading_spec.js
+++ /dev/null
@@ -1,47 +0,0 @@
-define(["underscore", "js/models/settings/course_grading_policy"], (_, CourseGradingPolicy) =>
- describe("CourseGradingPolicy", function() {
- beforeEach(function() {
- return this.model = new CourseGradingPolicy();
- });
-
- describe("parse", () =>
- it("sets a null grace period to 00:00", function() {
- const attrs = this.model.parse({grace_period: null});
- expect(attrs.grace_period).toEqual({
- hours: 0,
- minutes: 0
- });
- })
- );
-
- describe("parseGracePeriod", function() {
- it("parses a time in HH:MM format", function() {
- const time = this.model.parseGracePeriod("07:19");
- expect(time).toEqual({
- hours: 7,
- minutes: 19
- });
- });
-
- it("returns null on an incorrectly formatted string", function() {
- expect(this.model.parseGracePeriod("asdf")).toBe(null);
- expect(this.model.parseGracePeriod("7:19")).toBe(null);
- expect(this.model.parseGracePeriod("1000:00")).toBe(null);
- });
- });
-
- describe("validate", function() {
- it("enforces that the passing grade is <= the minimum grade to receive credit if credit is enabled", function() {
- this.model.set({minimum_grade_credit: 0.8, grace_period: '01:00', is_credit_course: true});
- this.model.set('grade_cutoffs', [0.9], {validate: true});
- expect(_.keys(this.model.validationError)).toContain('minimum_grade_credit');
- });
-
- it("does not enforce the passing grade limit in non-credit courses", function() {
- this.model.set({minimum_grade_credit: 0.8, grace_period: '01:00', is_credit_course: false});
- this.model.set({grade_cutoffs: [0.9]}, {validate: true});
- expect(this.model.validationError).toBe(null);
- });
- });
- })
-);
diff --git a/cms/static/js/spec/views/settings/main_spec.js b/cms/static/js/spec/views/settings/main_spec.js
deleted file mode 100644
index 43f95d584f05..000000000000
--- a/cms/static/js/spec/views/settings/main_spec.js
+++ /dev/null
@@ -1,369 +0,0 @@
-define([
- 'jquery', 'sinon', 'js/models/settings/course_details', 'js/views/settings/main',
- 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/js/spec_helpers/template_helpers'
-], function($, sinon, CourseDetailsModel, MainView, AjaxHelpers, TemplateHelpers) {
- 'use strict';
-
- var requests, xhrFactory;
-
- var SELECTORS = {
- entrance_exam_min_score: '#entrance-exam-minimum-score-pct',
- entrance_exam_enabled_field: '#entrance-exam-enabled',
- grade_requirement_div: '.div-grade-requirements div',
- add_course_learning_info: '.add-course-learning-info',
- delete_course_learning_info: '.delete-course-learning-info',
- add_course_instructor_info: '.add-course-instructor-info',
- remove_instructor_data: '.remove-instructor-data'
- };
-
- describe('Settings/Main', function() {
- var urlRoot = '/course/settings/org/DemoX/Demo_Course',
- modelData = {
- start_date: '2014-10-05T00:00:00Z',
- end_date: '2014-11-05T20:00:00Z',
- enrollment_start: '2014-10-00T00:00:00Z',
- enrollment_end: '2014-11-05T00:00:00Z',
- certificates_display_behavior: 'end',
- certificate_available_date: null,
- org: '',
- course_id: '',
- run: '',
- syllabus: null,
- title: '',
- subtitle: '',
- duration: '',
- description: '',
- short_description: '',
- overview: '',
- intro_video: null,
- effort: null,
- course_image_name: '',
- course_image_asset_path: '',
- 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',
- license: null,
- language: '',
- learning_info: [''],
- instructor_info: {
- instructors: [{
- name: '', title: '', organization: '', image: '', bio: ''
- }]
- },
- self_paced: false
- },
-
- mockSettingsPage = readFixtures('mock/mock-settings-page.underscore'),
- learningInfoTpl = readFixtures('course-settings-learning-fields.underscore'),
- instructorInfoTpl = readFixtures('course-instructor-details.underscore');
-
- beforeEach(function() {
- xhrFactory = sinon.useFakeXMLHttpRequest();
- requests = [];
- requests.currentIndex = 0;
- requests.restore = function() { xhrFactory.restore(); };
- xhrFactory.onCreate = function(req) { requests.push(req); };
- TemplateHelpers.installTemplates(['course-settings-learning-fields', 'course-instructor-details'], true);
- appendSetFixtures(mockSettingsPage);
- appendSetFixtures(
- $('