diff --git a/lms/static/js/ccx/collection/schedule_collection.js b/lms/static/js/ccx/collection/schedule_collection.js index 2516d1921ffd..c34c0d13bbf3 100644 --- a/lms/static/js/ccx/collection/schedule_collection.js +++ b/lms/static/js/ccx/collection/schedule_collection.js @@ -1,3 +1,8 @@ +/* eslint quote-props: "off", + no-param-reassign: "off", + consistent-return: "off", + array-callback-return: "off" +*/ (function(define) { 'use strict'; define([ @@ -67,6 +72,7 @@ // hide child (can be chapter, sequential or vertical) in collection. var scheduleJson = this.toJSON(); var errorMessage; + var unit; var units = this.findLineage( scheduleJson, @@ -79,12 +85,12 @@ errorMessage = this.validUnitDates(startDate, dueDate, units[units.length - 1]); if (!errorMessage) { units.map(this.show); - var unit = units[units.length - 1]; + unit = units[units.length - 1]; if (!_.isUndefined(unit)) { unit.start = startDate; unit.due = dueDate; if (unit.category === 'sequential' && unit.children) { - _.each(unit.children, function (vertical) { + _.each(unit.children, function(vertical) { vertical.start = startDate; vertical.due = dueDate; }); @@ -138,19 +144,19 @@ if (!chapterLocation) { return; } - _.each(tree, function (chapter, chapterIndex) { + _.each(tree, function(chapter, chapterIndex) { if (chapter.location === chapterLocation) { if (chapter.location === unit.location) { tree[chapterIndex] = unit; return true; } - _.each(chapter.children, function (subSection, subSectionIndex) { + _.each(chapter.children, function(subSection, subSectionIndex) { if (subSection.location === sequentialLocation && subSection.location === unit.location) { // update that subsection in tree tree[chapterIndex].children[subSectionIndex] = unit; - _.each(subSection.children, function (__, verticalIndex) { + _.each(subSection.children, function(__, verticalIndex) { // update start and due dates of verticals tree[chapterIndex].children[subSectionIndex]. children[verticalIndex].start = unit.start; @@ -169,14 +175,14 @@ pruned: function(tree, filter) { var self = this; return tree.filter(filter) - .map(function (node) { + .map(function(node) { var copy = {}; $.extend(copy, node); if (node.children) { copy.children = self.pruned(node.children, filter); } return copy; - }).filter(function (node) { + }).filter(function(node) { return node.children === undefined || node.children.length; }); }, @@ -191,7 +197,7 @@ changeVisibilityOfUnitInSchedule: function(units, applyVisibility) { var self = this; - units.map(function (unit) { + units.map(function(unit) { applyVisibility(unit); if (unit !== undefined && unit.children !== undefined) { self.changeVisibilityOfUnitInSchedule(unit.children, applyVisibility); @@ -213,6 +219,8 @@ validUnitDates: function(start, due, unit) { var errorMessage; + var parsedDueDate; + var parsedStartDate; // Start date is compulsory and due date is optional. if (_.isEmpty(start) && !_.isEmpty(due)) { errorMessage = StringUtils.interpolate( @@ -220,11 +228,11 @@ 'Please enter valid start ' + 'date and time for {type} "{displayName}".' ), - { 'displayName': unit.display_name, 'type': unit.category } + {'displayName': unit.display_name, 'type': unit.category} ); } else if (!_.isEmpty(start) && !_.isEmpty(due)) { - var parsedDueDate = moment(due, 'YYYY-MM-DD HH:mm'); - var parsedStartDate = moment(start, 'YYYY-MM-DD HH:mm'); + parsedDueDate = moment(due, 'YYYY-MM-DD HH:mm'); + parsedStartDate = moment(start, 'YYYY-MM-DD HH:mm'); if (parsedDueDate.isBefore(parsedStartDate)) { errorMessage = StringUtils.interpolate( gettext( @@ -241,9 +249,10 @@ findLineage: function(tree, chapterLocation, sequentialLocation, verticalLocation) { var units = []; var chapter = this.findUnitAtLocation(tree, chapterLocation); + var sequential; units[units.length] = chapter; if (sequentialLocation) { - var sequential = this.findUnitAtLocation( + sequential = this.findUnitAtLocation( chapter.children, sequentialLocation ); units[units.length] = sequential; @@ -262,7 +271,8 @@ }, findUnitAtLocation: function(seq, location) { - for (var i = 0; i < seq.length; i++) { + var i; + for (i = 0; i < seq.length; i++) { if (seq[i].location === location) { return seq[i]; } @@ -270,4 +280,4 @@ } }); }); -}).call(this, define || RequireJS.define); \ No newline at end of file +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/ccx/model/schedule_model.js b/lms/static/js/ccx/model/schedule_model.js index cb13f1245418..36c4bae40eea 100644 --- a/lms/static/js/ccx/model/schedule_model.js +++ b/lms/static/js/ccx/model/schedule_model.js @@ -1,6 +1,6 @@ (function(define) { 'use strict'; - define(['backbone'], function (Backbone) { + define(['backbone'], function(Backbone) { return Backbone.Model.extend({ defaults: { location: '', diff --git a/lms/static/js/ccx/view/ccx_schedule.js b/lms/static/js/ccx/view/ccx_schedule.js index ab6e54089741..c62ed6148560 100644 --- a/lms/static/js/ccx/view/ccx_schedule.js +++ b/lms/static/js/ccx/view/ccx_schedule.js @@ -1,4 +1,4 @@ -;(function (define) { +(function(define) { 'use strict'; define([ 'backbone', @@ -15,167 +15,165 @@ ScheduleRightContainerView, scheduleTemplate, HtmlUtils) { - return Backbone.View.extend({ + return Backbone.View.extend({ - initialize: function(options) { - var self = this; - this.template = HtmlUtils.template(scheduleTemplate); - this.saveCCXScheduleUrl = options.saveCCXScheduleUrl; - this.unsavedChanges = false; - this.collection.bind('change add remove reset', function () { - self.unsavedChanges = true; - self.render(); - }); - }, + initialize: function(options) { + var self = this; + this.template = HtmlUtils.template(scheduleTemplate); + this.saveCCXScheduleUrl = options.saveCCXScheduleUrl; + this.unsavedChanges = false; + this.collection.bind('change add remove reset', function() { + self.unsavedChanges = true; + self.render(); + }); + }, - render: function() { - HtmlUtils.setHtml( - this.$el, - this.template() - ); - this.loadScheduleTree(); - this.loadScheduleRightContainer(); - return this; - }, + render: function() { + HtmlUtils.setHtml( + this.$el, + this.template() + ); + this.loadScheduleTree(); + this.loadScheduleRightContainer(); + return this; + }, - loadScheduleRightContainer: function() { - // Right container consist of a form and alert messages. - this.scheduleRightContainer = new ScheduleRightContainerView({ - el: this.$("#ccx-schedule-form"), - collection: this.collection, - unsavedChanges: this.unsavedChanges - }); + loadScheduleRightContainer: function() { + // Right container consist of a form and alert messages. + this.scheduleRightContainer = new ScheduleRightContainerView({ + el: this.$('#ccx-schedule-form'), + collection: this.collection, + unsavedChanges: this.unsavedChanges + }); - this.scheduleRightContainer.render(); - this.$('#ajax-error').hide(); - this.listenTo( - this.scheduleRightContainer, - 'showUnitInScheduleTree', - this.showUnitInScheduleTree - ); - this.listenTo( - this.scheduleRightContainer, - 'showAllUnitsInScheduleTree', - this.showAllUnitsInScheduleTree - ); - this.listenTo( - this.scheduleRightContainer, - 'saveSchedule', - this.saveSchedule - ); - }, + this.scheduleRightContainer.render(); + this.$('#ajax-error').hide(); + this.listenTo( + this.scheduleRightContainer, + 'showUnitInScheduleTree', + this.showUnitInScheduleTree + ); + this.listenTo( + this.scheduleRightContainer, + 'showAllUnitsInScheduleTree', + this.showAllUnitsInScheduleTree + ); + this.listenTo( + this.scheduleRightContainer, + 'saveSchedule', + this.saveSchedule + ); + }, - loadScheduleTree: function() { - // This data will be render on schedule tree. - this.scheduleTreeView = new ScheduleTree({ - el: this.$("#new-ccx-schedule"), - collection: this.collection - }); + loadScheduleTree: function() { + // This data will be render on schedule tree. + this.scheduleTreeView = new ScheduleTree({ + el: this.$('#new-ccx-schedule'), + collection: this.collection + }); - this.scheduleTreeView.render(); - this.listenTo( - this.scheduleTreeView, - 'hideAllUnitFromScheduleTree', - this.hideAllUnitFromScheduleTree - ); - this.listenTo( - this.scheduleTreeView, - 'hideUnitFromScheduleTree', - this.hideUnitFromScheduleTree - ); - this.listenTo( - this.scheduleTreeView, - 'applyUnitToScheduleTree', - this.applyUnitToScheduleTree - ); - }, + this.scheduleTreeView.render(); + this.listenTo( + this.scheduleTreeView, + 'hideAllUnitFromScheduleTree', + this.hideAllUnitFromScheduleTree + ); + this.listenTo( + this.scheduleTreeView, + 'hideUnitFromScheduleTree', + this.hideUnitFromScheduleTree + ); + this.listenTo( + this.scheduleTreeView, + 'applyUnitToScheduleTree', + this.applyUnitToScheduleTree + ); + }, - saveSchedule: function() { - // saves schedule on server. - var self = this; - Backbone.ajax({ - url: this.saveCCXScheduleUrl, - type: 'POST', - contentType: 'application/json', - data: JSON.stringify(this.collection), - success: function (data) { - self.unsavedChanges = false; - self.render(); - $('#grading-policy').text(HtmlUtils.ensureHtml(data.grading_policy)); - }, - error: function (jqXHR) { - console.log(jqXHR.responseText); - self.showErrorMessage(); - self.scheduleRightContainer.resetSaveChangesButton(); - } - }); - }, - - applyUnitToScheduleTree: function(dateType, - newDate, - chapterLocation, - sequentialLocation, - verticalLocation) { - // updates collection on start, due date change in chapter or sequential - this.errorMessage = this.collection.applyUnitToScheduleTree( - dateType, - newDate, - chapterLocation, - sequentialLocation, - verticalLocation - ); - if (this.errorMessage) { - this.showErrorMessage(); + saveSchedule: function() { + // saves schedule on server. + var self = this; + Backbone.ajax({ + url: this.saveCCXScheduleUrl, + type: 'POST', + contentType: 'application/json', + data: JSON.stringify(this.collection), + success: function(data) { + self.unsavedChanges = false; + self.render(); + $('#grading-policy').text(HtmlUtils.ensureHtml(data.grading_policy)); + }, + error: function() { + self.showErrorMessage(); + self.scheduleRightContainer.resetSaveChangesButton(); } - }, + }); + }, - hideUnitFromScheduleTree: function(chapterLocation, sequentialLocation, - verticalLocation) { - // hide child (can be chapter, sequential or vertical) in collection. - this.collection.hideUnitFromScheduleTree( - chapterLocation, - sequentialLocation, - verticalLocation - ); - }, + applyUnitToScheduleTree: function(dateType, + newDate, + chapterLocation, + sequentialLocation, + verticalLocation) { + // updates collection on start, due date change in chapter or sequential + this.errorMessage = this.collection.applyUnitToScheduleTree( + dateType, + newDate, + chapterLocation, + sequentialLocation, + verticalLocation + ); + if (this.errorMessage) { + this.showErrorMessage(); + } + }, - hideAllUnitFromScheduleTree: function() { - // clear schedule tree on remove all click - this.collection.hideAllUnitFromScheduleTree(); - }, + hideUnitFromScheduleTree: function(chapterLocation, sequentialLocation, + verticalLocation) { + // hide child (can be chapter, sequential or vertical) in collection. + this.collection.hideUnitFromScheduleTree( + chapterLocation, + sequentialLocation, + verticalLocation + ); + }, - showUnitInScheduleTree: function(chapterLocation, sequentialLocation, verticalLocation, - startDate, dueDate) { - // hide child (can be chapter, sequential or vertical) in collection. - this.errorMessage = this.collection.showUnitInScheduleTree( - chapterLocation, - sequentialLocation, - verticalLocation, - startDate, - dueDate - ); + hideAllUnitFromScheduleTree: function() { + // clear schedule tree on remove all click + this.collection.hideAllUnitFromScheduleTree(); + }, - if (this.errorMessage) { - this.showErrorMessage(); - } - }, + showUnitInScheduleTree: function(chapterLocation, sequentialLocation, verticalLocation, + startDate, dueDate) { + // hide child (can be chapter, sequential or vertical) in collection. + this.errorMessage = this.collection.showUnitInScheduleTree( + chapterLocation, + sequentialLocation, + verticalLocation, + startDate, + dueDate + ); - showAllUnitsInScheduleTree: function() { - // show all units i.e chapters, subsections and verticals - // in schedule tree - this.collection.showAllUnitsInScheduleTree(); - }, + if (this.errorMessage) { + this.showErrorMessage(); + } + }, - showErrorMessage: function() { - if (this.errorMessage) { - HtmlUtils.setHtml( - this.$('#ccx_schedule_error_message'), - HtmlUtils.ensureHtml(this.errorMessage) - ); - } - this.$('#ajax-error').show().focus(); + showAllUnitsInScheduleTree: function() { + // show all units i.e chapters, subsections and verticals + // in schedule tree + this.collection.showAllUnitsInScheduleTree(); + }, + + showErrorMessage: function() { + if (this.errorMessage) { + HtmlUtils.setHtml( + this.$('#ccx_schedule_error_message'), + HtmlUtils.ensureHtml(this.errorMessage) + ); } - }); - } - ); -}).call(this, define || RequireJS.define); \ No newline at end of file + this.$('#ajax-error').show().focus(); + } + }); + }); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/ccx/view/schedule_date_button.js b/lms/static/js/ccx/view/schedule_date_button.js index 6d0f2b850d9f..44a77fa118e0 100644 --- a/lms/static/js/ccx/view/schedule_date_button.js +++ b/lms/static/js/ccx/view/schedule_date_button.js @@ -1,3 +1,4 @@ +/* eslint no-shadow: "off" */ (function(define) { 'use strict'; define([ @@ -13,116 +14,120 @@ gettext, scheduleTreeDateButtonTemplate, HtmlUtils) { - return Backbone.View.extend({ + return Backbone.View.extend({ - initialize: function(options) { - this.dateType = options.dateType; - this.date = options.date; - this.template = HtmlUtils.template(scheduleTreeDateButtonTemplate); - }, + initialize: function(options) { + this.dateType = options.dateType; + this.date = options.date; + this.template = HtmlUtils.template(scheduleTreeDateButtonTemplate); + }, - render: function() { - HtmlUtils.setHtml( - this.$el, - this.template({date: this.date}) - ); - this.location = this.$el.data("location"); - var $dateChangeButton = $(this.$el.find("button")); + render: function() { + var $dateChangeButton; + HtmlUtils.setHtml( + this.$el, + this.template({date: this.date}) + ); + this.location = this.$el.data('location'); + $dateChangeButton = $(this.$el.find('button')); - $dateChangeButton.attr('href', '#enter-date-modal').leanModal({closeButton: '.close-modal'}); - $dateChangeButton.click(this.editDateCCXSchedule()); + $dateChangeButton.attr('href', '#enter-date-modal').leanModal({closeButton: '.close-modal'}); + $dateChangeButton.click(this.editDateCCXSchedule()); - return this; - }, + return this; + }, - editDateCCXSchedule: function() { - var self = this; - return function () { - var dateParts; - var row = $(this).closest('tr'); - var modal = $('#enter-date-modal') - .data('what', self.dateType) - .data('location', row.data('location')); + editDateCCXSchedule: function() { + var self = this; + return function() { + var dateParts; + var date; + var time; + var row = $(this).closest('tr'); + var modal = $('#enter-date-modal') + .data('what', self.dateType) + .data('location', row.data('location')); - modal.find('h2').text( - self.dateType === 'due' ? HtmlUtils.ensureHtml(gettext("Enter Due Date and Time")) : - HtmlUtils.ensureHtml(gettext("Enter Start Date and Time")) - ); + modal.find('h2').text( + self.dateType === 'due' ? HtmlUtils.ensureHtml(gettext('Enter Due Date and Time')) : + HtmlUtils.ensureHtml(gettext('Enter Start Date and Time')) + ); - if (self.date) { - // if already date is set then populate modal with that date. - dateParts = self.date ? self.date.split(' ') : ['', '']; - var date = dateParts[0]; - var time = dateParts[1]; + if (self.date) { + // if already date is set then populate modal with that date. + dateParts = self.date ? self.date.split(' ') : ['', '']; + date = dateParts[0]; + time = dateParts[1]; - modal.find('input[name=date]').val(date); - modal.find('input[name=time]').val(time); - } + modal.find('input[name=date]').val(date); + modal.find('input[name=time]').val(time); + } - modal.focus(); - $(document).on('focusin', function (event) { - try { - // When focusin event triggers in document it will detects that if object - // is modal (dialog) then it will shift the focus to cross icon - // the first element in dialog. - if (!_.isUndefined(event.target.closest('.modal').id) && - event.target.closest('.modal').id !== 'enter-date-modal' && - event.target.id !== 'enter-date-modal') { - event.preventDefault(); - modal.find('.close-modal').focus(); - } - } catch (err) { - // if error then try to focus close icon. + modal.focus(); + $(document).on('focusin', function(event) { + try { + // When focusin event triggers in document it will detects that if object + // is modal (dialog) then it will shift the focus to cross icon + // the first element in dialog. + if (!_.isUndefined(event.target.closest('.modal').id) && + event.target.closest('.modal').id !== 'enter-date-modal' && + event.target.id !== 'enter-date-modal') { event.preventDefault(); modal.find('.close-modal').focus(); } - }); + } catch (err) { + // if error then try to focus close icon. + event.preventDefault(); + modal.find('.close-modal').focus(); + } + }); - modal.find('.close-modal').click(function () { - // on close model click, focus back last selected element. - $(document).off('focusin'); - $(window).scrollTop(self.$el.position().top); - self.$el.focus(); - }); + modal.find('.close-modal').click(function() { + // on close model click, focus back last selected element. + $(document).off('focusin'); + $(window).scrollTop(self.$el.position().top); + self.$el.focus(); + }); - modal.find('form').off('submit').on('submit', function (event) { - // Submits valid start or due date to ccx_schedule.js file. which process it - // and if date is change on subsection then it will propagate change to - // child nodes. - event.preventDefault(); - modal.find('#date-modal-error-message').empty(); - var valid_time = /^\d{1,2}:\d{2}?$/; - var date = $(this).find('input[name=date]').val(), - time = $(this).find('input[name=time]').val(); - var valid_date = new Date(date); + modal.find('form').off('submit').on('submit', function(event) { + // Submits valid start or due date to ccx_schedule.js file. which process it + // and if date is change on subsection then it will propagate change to + // child nodes. + var newDate; + var validTime = /^\d{1,2}:\d{2}?$/; + var date = $(this).find('input[name=date]').val(), + time = $(this).find('input[name=time]').val(); + var validDate = new Date(date); - if (isNaN(valid_date.valueOf())) { - modal.find('#date-modal-error-message').text(HtmlUtils.ensureHtml( - gettext('Please enter a valid date')) - ); - return; - } + event.preventDefault(); + modal.find('#date-modal-error-message').empty(); - if (!time.match(valid_time)) { - modal.find('#date-modal-error-message').text(HtmlUtils.ensureHtml( - gettext('Please enter a valid time')) - ); - return; - } + if (isNaN(validDate.valueOf())) { + modal.find('#date-modal-error-message').text(HtmlUtils.ensureHtml( + gettext('Please enter a valid date')) + ); + return; + } - $(window).scrollTop(self.$el.position().top); - self.$el.focus(); - var newDate = date + ' ' + time; - if (!self.date || newDate !== self.date) { - self.trigger( - 'updateDate', self.dateType, newDate, self.location - ); - } - modal.find('.close-modal').click(); - }); - }; - } - }); - } - ); + if (!time.match(validTime)) { + modal.find('#date-modal-error-message').text(HtmlUtils.ensureHtml( + gettext('Please enter a valid time')) + ); + return; + } + + $(window).scrollTop(self.$el.position().top); + self.$el.focus(); + newDate = date + ' ' + time; + if (!self.date || newDate !== self.date) { + self.trigger( + 'updateDate', self.dateType, newDate, self.location + ); + } + modal.find('.close-modal').click(); + }); + }; + } + }); + }); }).call(this, define || RequireJS.define); diff --git a/lms/static/js/ccx/view/schedule_right_container.js b/lms/static/js/ccx/view/schedule_right_container.js index 4b9c71421e3a..a381340fd4a9 100644 --- a/lms/static/js/ccx/view/schedule_right_container.js +++ b/lms/static/js/ccx/view/schedule_right_container.js @@ -1,3 +1,4 @@ +/* eslint quote-props: "off" */ (function(define) { 'use strict'; define([ @@ -9,7 +10,7 @@ 'text!templates/ccx/underscore/form.underscore', 'edx-ui-toolkit/js/utils/html-utils', 'jquery.timepicker' - ], function ( + ], function( Backbone, $, _, @@ -17,210 +18,209 @@ scheduleRightContainerTemplate, scheduleFormTemplate, HtmlUtils) { - return Backbone.View.extend({ - - events: { - 'change select#ccx_chapter': 'onChapterSelect', - 'change select#ccx_sequential': 'onSubsectionSelect', - 'change select#ccx_vertical': 'onVerticalSelect', - 'change .date': 'onDateSelect', - 'click #add-unit-button': 'addUnitInScheduleTree', - 'click #add-all': 'showAllUnitsInScheduleTree', - 'click #save-changes': 'saveSchedule' - }, - - initialize: function(options) { - this.templateContainer = HtmlUtils.template(scheduleRightContainerTemplate); - this.templateForm = HtmlUtils.template(scheduleFormTemplate); - this.unsavedChanges = options.unsavedChanges; - - // Hidden data will be shown into form, - // from there user can add this data to schedule tree - this.chapters = this.collection.filterFormData(); - this.resetFormFlags(); - }, - - render: function() { - if (this.chapters) { - this.loadRightContainerCCXSchedule(); - } - - return this; - }, + return Backbone.View.extend({ + + events: { + 'change select#ccx_chapter': 'onChapterSelect', + 'change select#ccx_sequential': 'onSubsectionSelect', + 'change select#ccx_vertical': 'onVerticalSelect', + 'change .date': 'onDateSelect', + 'click #add-unit-button': 'addUnitInScheduleTree', + 'click #add-all': 'showAllUnitsInScheduleTree', + 'click #save-changes': 'saveSchedule' + }, + + initialize: function(options) { + this.templateContainer = HtmlUtils.template(scheduleRightContainerTemplate); + this.templateForm = HtmlUtils.template(scheduleFormTemplate); + this.unsavedChanges = options.unsavedChanges; + + // Hidden data will be shown into form, + // from there user can add this data to schedule tree + this.chapters = this.collection.filterFormData(); + this.resetFormFlags(); + }, + + render: function() { + if (this.chapters) { + this.loadRightContainerCCXSchedule(); + } - loadRightContainerCCXSchedule: function() { - HtmlUtils.setHtml( - this.$el, - this.templateContainer({ - chaptersAvailable: (this.chapters && !_.isEmpty(this.chapters)), - unsavedChanges: this.unsavedChanges, - addUnitCCXForm: this.templateForm({ - chapters: this.chapters, - selectedChapter: this.selectedChapter, - selectedSubsection: this.selectedSubsection, - enableAddUnitToScheduleButton: this.enableAddUnitToScheduleButton - }) + return this; + }, + + loadRightContainerCCXSchedule: function() { + HtmlUtils.setHtml( + this.$el, + this.templateContainer({ + chaptersAvailable: (this.chapters && !_.isEmpty(this.chapters)), + unsavedChanges: this.unsavedChanges, + addUnitCCXForm: this.templateForm({ + chapters: this.chapters, + selectedChapter: this.selectedChapter, + selectedSubsection: this.selectedSubsection, + enableAddUnitToScheduleButton: this.enableAddUnitToScheduleButton }) + }) + ); + + // attach date and time pickers + this.$el.find('.datepair .time').timepicker({ + 'showDuration': true, + 'timeFormat': 'G:i', + 'autoclose': true + }); + + this.$el.find('.datepair .date').datepicker({ + 'dateFormat': 'yy-mm-dd', + 'autoclose': true + }); + }, + + + addUnitInScheduleTree: function(e) { + // add unit to schedule tree. To make contents visible to students + // a unit can be chapter, sequential or a vertical. + var chapterLocation = this.$el.find('#ccx_chapter').val(); + var sequentialLocation = this.$el.find('#ccx_sequential').val(); + var verticalLocation = this.$el.find('#ccx_vertical').val(); + var startDate = this.getDateTime('start'); + var dueDate = this.getDateTime('due'); + e.preventDefault(); + + this.trigger( + 'showUnitInScheduleTree', + chapterLocation, + sequentialLocation === 'all' ? null : sequentialLocation, + verticalLocation === 'all' ? null : verticalLocation, + startDate, + dueDate + ); + }, + + showAllUnitsInScheduleTree: function(e) { + // add unit to schedule tree. + e.preventDefault(); + this.trigger( + 'showAllUnitsInScheduleTree' + ); + }, + + onChapterSelect: function(e) { + // On chapter select populate subsection drop box. + var $chapterSelect = $(e.currentTarget); + var chapterLocation = $chapterSelect.val(); + var $sequentialSelect = this.$el.find('#ccx_sequential'); + if (chapterLocation !== 'none') { + this.selectedChapter = this.collection.findUnit( + this.chapters, chapterLocation ); - - // attach date and time pickers - this.$el.find('.datepair .time').timepicker({ - 'showDuration': true, - 'timeFormat': 'G:i', - 'autoclose': true - }); - - this.$el.find('.datepair .date').datepicker({ - 'dateFormat': 'yy-mm-dd', - 'autoclose': true - }); - }, - - - addUnitInScheduleTree: function(e) { - // add unit to schedule tree. To make contents visible to students - // a unit can be chapter, sequential or a vertical. - e.preventDefault(); - var chapterLocation = this.$el.find("#ccx_chapter").val(); - var sequentialLocation = this.$el.find("#ccx_sequential").val(); - var verticalLocation = this.$el.find("#ccx_vertical").val(); - var startDate = this.getDateTime("start"); - var dueDate = this.getDateTime("due"); - - this.trigger( - 'showUnitInScheduleTree', - chapterLocation, - sequentialLocation === 'all' ? null : sequentialLocation, - verticalLocation === 'all' ? null : verticalLocation, - startDate, - dueDate - ); - }, - - showAllUnitsInScheduleTree: function(e) { - // add unit to schedule tree. - e.preventDefault(); - this.trigger( - 'showAllUnitsInScheduleTree' - ); - }, - - onChapterSelect: function(e) { - // On chapter select populate subsection drop box. - var $chapterSelect = $(e.currentTarget); - var chapterLocation = $chapterSelect.val(); - var $sequentialSelect = this.$el.find('#ccx_sequential'); - if (chapterLocation !== 'none') { - this.selectedChapter = this.collection.findUnit( - this.chapters, chapterLocation - ); - this.enableAddUnitToScheduleButton = true; - $sequentialSelect.empty(); - this.render(); - } else { - this.resetFormFlags(); - this.render(); - } - }, - - onSubsectionSelect: function(e) { - // On subsection aka sequential select populate verticals drop box. - var $subSectionSelect = $(e.currentTarget); - var subSectionLocation = $subSectionSelect.val(); - var $verticalSelect = this.$el.find('#ccx_vertical'); - - if (subSectionLocation !== 'all') { - this.selectedSubsection = this.collection.findUnit( - this.chapters, - this.selectedChapter.location, - subSectionLocation - ); - $verticalSelect.empty(); - this.render(); - } else { - this.resetSubsectionSelectFlags(); - this.render(); - } - }, - - onVerticalSelect: function(e) { - // On vertical select disable edit date sections. - var $verticalSelect = $(e.currentTarget); - var verticalLocation = $verticalSelect.val(); - - if (verticalLocation !== 'all') { - this.disableFields(this.$('.ccx_start_date_time_fields')); - this.disableFields(this.$('.ccx_due_date_time_fields')); - } else { - this.enableFields(this.$('.ccx_start_date_time_fields')); - this.enableFields(this.$('.ccx_due_date_time_fields')); - } - }, - - saveSchedule: function(e) { - // save schedule on server. - e.preventDefault(); - var $button = $(e.currentTarget); - $button.prop('disabled', true).text(gettext("Saving")); - this.trigger( - 'saveSchedule' + this.enableAddUnitToScheduleButton = true; + $sequentialSelect.empty(); + this.render(); + } else { + this.resetFormFlags(); + this.render(); + } + }, + + onSubsectionSelect: function(e) { + // On subsection aka sequential select populate verticals drop box. + var $subSectionSelect = $(e.currentTarget); + var subSectionLocation = $subSectionSelect.val(); + var $verticalSelect = this.$el.find('#ccx_vertical'); + + if (subSectionLocation !== 'all') { + this.selectedSubsection = this.collection.findUnit( + this.chapters, + this.selectedChapter.location, + subSectionLocation ); - }, - - resetSaveChangesButton: function() { - // After collection save enable save changes button - this.$el.find('#save-changes').prop( - 'disabled', false - ).text(gettext("Save changes")); - }, - - onDateSelect: function(e) { - // on date select from date picker format it. - var $date = $(e.currentTarget); - var date = $date.datepicker("getDate"); - - if (date) { - HtmlUtils.setHtml( - $(this), - $.datepicker.formatDate("yy-mm-dd", date) - ); - } - }, - - resetFormFlags: function() { - // reset for flag to disable select boxes (subsection, units) - // and edit date sections. - this.selectedChapter = undefined; + $verticalSelect.empty(); + this.render(); + } else { this.resetSubsectionSelectFlags(); - this.enableAddUnitToScheduleButton = false; - }, - - resetSubsectionSelectFlags: function() { - // reset for flag to disable select box (units) - // and edit date sections. - this.selectedSubsection = undefined; - }, - - disableFields: function($selector) { - // disable select, input or button field under selector. - $selector.find('select,input,button').prop('disabled', true); - }, - - enableFields: function($selector) { - // enable select, input or button field under selector. - $selector.find('select,input,button').prop('disabled', false); - }, - - getDateTime: function(dateType) { - var date = this.$('input[name=' + dateType + '_date]').val(); - var time = this.$('input[name=' + dateType + '_time]').val(); - time = _.isEmpty(time) ? "00:00" : time; - if (date && time) { - return date + ' ' + time; - } - return null; + this.render(); + } + }, + + onVerticalSelect: function(e) { + // On vertical select disable edit date sections. + var $verticalSelect = $(e.currentTarget); + var verticalLocation = $verticalSelect.val(); + + if (verticalLocation !== 'all') { + this.disableFields(this.$('.ccx_start_date_time_fields')); + this.disableFields(this.$('.ccx_due_date_time_fields')); + } else { + this.enableFields(this.$('.ccx_start_date_time_fields')); + this.enableFields(this.$('.ccx_due_date_time_fields')); + } + }, + + saveSchedule: function(e) { + // save schedule on server. + var $button = $(e.currentTarget); + e.preventDefault(); + $button.prop('disabled', true).text(gettext('Saving')); + this.trigger( + 'saveSchedule' + ); + }, + + resetSaveChangesButton: function() { + // After collection save enable save changes button + this.$el.find('#save-changes').prop( + 'disabled', false + ).text(gettext('Save changes')); + }, + + onDateSelect: function(e) { + // on date select from date picker format it. + var $date = $(e.currentTarget); + var date = $date.datepicker('getDate'); + + if (date) { + HtmlUtils.setHtml( + $(this), + $.datepicker.formatDate('yy-mm-dd', date) + ); + } + }, + + resetFormFlags: function() { + // reset for flag to disable select boxes (subsection, units) + // and edit date sections. + this.selectedChapter = undefined; + this.resetSubsectionSelectFlags(); + this.enableAddUnitToScheduleButton = false; + }, + + resetSubsectionSelectFlags: function() { + // reset for flag to disable select box (units) + // and edit date sections. + this.selectedSubsection = undefined; + }, + + disableFields: function($selector) { + // disable select, input or button field under selector. + $selector.find('select,input,button').prop('disabled', true); + }, + + enableFields: function($selector) { + // enable select, input or button field under selector. + $selector.find('select,input,button').prop('disabled', false); + }, + + getDateTime: function(dateType) { + var date = this.$('input[name=' + dateType + '_date]').val(); + var time = this.$('input[name=' + dateType + '_time]').val(); + time = _.isEmpty(time) ? '00:00' : time; + if (date && time) { + return date + ' ' + time; } - }); - } - ); -}).call(this, define || RequireJS.define); \ No newline at end of file + return null; + } + }); + }); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/ccx/view/schedule_tree.js b/lms/static/js/ccx/view/schedule_tree.js index 3b29a1eaa3d6..cbde039ffe0a 100644 --- a/lms/static/js/ccx/view/schedule_tree.js +++ b/lms/static/js/ccx/view/schedule_tree.js @@ -1,3 +1,4 @@ +/* eslint dollar-sign/dollar-sign: "off" */ (function(define) { 'use strict'; define([ @@ -8,7 +9,7 @@ 'text!templates/ccx/underscore/unit.underscore', 'text!templates/ccx/underscore/tree.underscore', 'edx-ui-toolkit/js/utils/html-utils' - ], function ( + ], function( Backbone, $, _, @@ -16,183 +17,187 @@ scheduleTreeNodeTemplate, scheduleTreeContentTemplate, HtmlUtils) { - return Backbone.View.extend({ - - events: { - 'click .remove-unit': 'removeUnitFromTree', - 'click #remove-all': 'removeAllUnitFromTree', - 'click .toggle-collapse': 'toggleNodeState', - 'click #ccx_expand_all_btn': 'expandAll', - 'click #ccx_collapse_all_btn': 'collapseAll' - }, - - initialize: function () { - this.templateTreeNode = HtmlUtils.template(scheduleTreeNodeTemplate); - this.templateTree = HtmlUtils.template(scheduleTreeContentTemplate); - }, - - render: function () { - this.chapters = this.collection.filterTreeData(); - if (this.chapters) { - HtmlUtils.setHtml( - this.$el, - this.templateTree({ - chapters: this.chapters, - templateTreeNode: this.templateTreeNode - }) - ); - this.configureEditDateViews(); - } - return this; - }, - - configureEditDateViews: function () { - var self = this; - this.$('table.ccx-schedule .due-date').each(function () { - var date = $(this).data('date'); - var scheduleDateButtonView = new DateButtonView({ - el: $(this), - date: date, - dateType: 'due' - }); - scheduleDateButtonView.render(); - self.listenTo( - scheduleDateButtonView, - 'updateDate', - self.updateDate - ); - }); - - this.$el.find('table.ccx-schedule .start-date').each(function () { - var date = $(this).data('date'); - var scheduleDateButtonView = new DateButtonView({ - el: $(this), - date: date, - dateType: 'start' - }); - scheduleDateButtonView.render(); - self.listenTo( - scheduleDateButtonView, - 'updateDate', - self.updateDate - ); + return Backbone.View.extend({ + + events: { + 'click .remove-unit': 'removeUnitFromTree', + 'click #remove-all': 'removeAllUnitFromTree', + 'click .toggle-collapse': 'toggleNodeState', + 'click #ccx_expand_all_btn': 'expandAll', + 'click #ccx_collapse_all_btn': 'collapseAll' + }, + + initialize: function() { + this.templateTreeNode = HtmlUtils.template(scheduleTreeNodeTemplate); + this.templateTree = HtmlUtils.template(scheduleTreeContentTemplate); + }, + + render: function() { + this.chapters = this.collection.filterTreeData(); + if (this.chapters) { + HtmlUtils.setHtml( + this.$el, + this.templateTree({ + chapters: this.chapters, + templateTreeNode: this.templateTreeNode + }) + ); + this.configureEditDateViews(); + } + return this; + }, + + configureEditDateViews: function() { + var self = this; + this.$('table.ccx-schedule .due-date').each(function() { + var date = $(this).data('date'); + var scheduleDateButtonView = new DateButtonView({ + el: $(this), + date: date, + dateType: 'due' }); - }, - - updateDate: function (dateType, newDate, location) { - var path = location.split(' '); - var chapterLocation = path[0]; - var sequentialLocation = path[1]; - var verticalLocation = path[2]; - - this.trigger( - 'applyUnitToScheduleTree', - dateType, - newDate, - chapterLocation, - sequentialLocation, - verticalLocation + scheduleDateButtonView.render(); + self.listenTo( + scheduleDateButtonView, + 'updateDate', + self.updateDate ); - }, - - removeUnitFromTree: function (e) { - // remove a unit which can be chapter, sequential - // or vertical from schedule tree - e.preventDefault(); - var target = e.target || e.srcElement; - var location = $(target).data('location'); - var path = location.split(' '); - var chapterLocation = path[0]; - var sequentialLocation = path[1]; - var verticalLocation = path[2]; - - this.trigger( - 'hideUnitFromScheduleTree', - chapterLocation, - sequentialLocation, - verticalLocation + }); + + this.$el.find('table.ccx-schedule .start-date').each(function() { + var date = $(this).data('date'); + var scheduleDateButtonView = new DateButtonView({ + el: $(this), + date: date, + dateType: 'start' + }); + scheduleDateButtonView.render(); + self.listenTo( + scheduleDateButtonView, + 'updateDate', + self.updateDate ); - }, - - removeAllUnitFromTree: function () { - this.trigger('hideAllUnitFromScheduleTree'); - }, - - toggleNodeState: function (e) { - // expand or collapse node (chapter or sequential) - e.preventDefault(); - var target = e.target || e.srcElement; - var row = $(target).closest('tr'); - var children = this.getChildrenInView(row); - - if (row.is('.expanded')) { - $(target).attr('aria-expanded', 'false'); - $(target).find(".fa-caret-down").removeClass('fa-caret-down').addClass('fa-caret-right'); - row.removeClass('expanded').addClass('collapsed'); - children.hide(); + }); + }, + + updateDate: function(dateType, newDate, location) { + var path = location.split(' '); + var chapterLocation = path[0]; + var sequentialLocation = path[1]; + var verticalLocation = path[2]; + + this.trigger( + 'applyUnitToScheduleTree', + dateType, + newDate, + chapterLocation, + sequentialLocation, + verticalLocation + ); + }, + + removeUnitFromTree: function(e) { + // remove a unit which can be chapter, sequential + // or vertical from schedule tree + var target = e.target || e.srcElement; + var location = $(target).data('location'); + var path = location.split(' '); + var chapterLocation = path[0]; + var sequentialLocation = path[1]; + var verticalLocation = path[2]; + e.preventDefault(); + + this.trigger( + 'hideUnitFromScheduleTree', + chapterLocation, + sequentialLocation, + verticalLocation + ); + }, + + removeAllUnitFromTree: function() { + this.trigger('hideAllUnitFromScheduleTree'); + }, + + toggleNodeState: function(e) { + // expand or collapse node (chapter or sequential) + var target = e.target || e.srcElement; + var row = $(target).closest('tr'); + var children = this.getChildrenInView(row); + var depth; + var $childNodes; + + e.preventDefault(); + if (row.is('.expanded')) { + $(target).attr('aria-expanded', 'false'); + $(target).find('.fa-caret-down').removeClass('fa-caret-down') + .addClass('fa-caret-right'); + row.removeClass('expanded').addClass('collapsed'); + children.hide(); + } else { + $(target).attr('aria-expanded', 'true'); + $(target).find('.fa-caret-right').removeClass('fa-caret-right') + .addClass('fa-caret-down'); + row.removeClass('collapsed').addClass('expanded'); + depth = $(row).data('depth'); + $childNodes = children.filter('.collapsed'); + if ($childNodes.length <= 0) { + children.show(); } else { - $(target).attr('aria-expanded', 'true'); - $(target).find(".fa-caret-right").removeClass('fa-caret-right').addClass('fa-caret-down'); - row.removeClass('collapsed').addClass('expanded'); - var depth = $(row).data('depth'); - var $childNodes = children.filter('.collapsed'); - if ($childNodes.length <= 0) { - children.show(); - } else { - // this will expand units. - $childNodes.each(function () { - var depthChild = $(this).data('depth'); - if (depth === (depthChild - 1)) { - $(this).show(); - } - }); - } + // this will expand units. + $childNodes.each(function() { + var depthChild = $(this).data('depth'); + if (depth === (depthChild - 1)) { + $(this).show(); + } + }); } - }, - - getChildrenInView: function (row) { - var depth = $(row).data('depth'); - return $(row).nextUntil( - $(row).siblings().filter(function () { - return $(this).data('depth') <= depth; - }) - ); - }, - - expandAll: function () { - var self = this; - this.$('table.ccx-schedule > tbody > tr').each(function () { - var row = $(this); - if (!row.is('.expanded')) { - var children = self.getChildrenInView(row); - row.find(".ccx_sr_alert").attr("aria-expanded", "true"); - row.find(".fa-caret-right").removeClass( - 'fa-caret-right' - ).addClass('fa-caret-down'); - row.removeClass('collapsed').addClass('expanded'); - children.filter('.collapsed').each(function () { - children = children.not(self.getChildrenInView(this)); - }); - children.show(); - } - }); - }, - - collapseAll: function () { - this.$('table.ccx-schedule > tbody > tr').each(function () { - var row = $(this); - if (row.is('.expanded')) { - $(row).find('.ccx_sr_alert').attr('aria-expanded', 'false'); - $(row).find('.fa-caret-down').removeClass( - 'fa-caret-down').addClass('fa-caret-right' - ); - row.removeClass('expanded').addClass('collapsed'); - } - }); - this.$el.find('table.ccx-schedule .sequential,.vertical').hide(); } + }, + + getChildrenInView: function(row) { + var depth = $(row).data('depth'); + return $(row).nextUntil( + $(row).siblings().filter(function() { + return $(this).data('depth') <= depth; + }) + ); + }, + + expandAll: function() { + var self = this; + this.$('table.ccx-schedule > tbody > tr').each(function() { + var row = $(this); + var children; + + if (!row.is('.expanded')) { + children = self.getChildrenInView(row); + row.find('.ccx_sr_alert').attr('aria-expanded', 'true'); + row.find('.fa-caret-right').removeClass( + 'fa-caret-right' + ).addClass('fa-caret-down'); + row.removeClass('collapsed').addClass('expanded'); + children.filter('.collapsed').each(function() { + children = children.not(self.getChildrenInView(this)); + }); + children.show(); + } + }); + }, - }); - } - ); -}).call(this, define || RequireJS.define); \ No newline at end of file + collapseAll: function() { + this.$('table.ccx-schedule > tbody > tr').each(function() { + var row = $(this); + if (row.is('.expanded')) { + $(row).find('.ccx_sr_alert').attr('aria-expanded', 'false'); + $(row).find('.fa-caret-down') + .removeClass('fa-caret-down') + .addClass('fa-caret-right'); + row.removeClass('expanded').addClass('collapsed'); + } + }); + this.$el.find('table.ccx-schedule .sequential,.vertical').hide(); + } + }); + }); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/spec/ccx/schedule_spec.js b/lms/static/js/spec/ccx/schedule_spec.js index 31786a369663..e8d8a4a1d052 100644 --- a/lms/static/js/spec/ccx/schedule_spec.js +++ b/lms/static/js/spec/ccx/schedule_spec.js @@ -1,283 +1,290 @@ +/* eslint quote-props: "off", no-undef: "off", no-param-reassign: "off" */ define([ - 'jquery', - 'underscore', - 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', - 'js/ccx/collection/schedule_collection', - 'js/ccx/view/ccx_schedule' - ], - function ($, _, AjaxHelpers, ScheduleCollection, ScheduleView) { - 'use strict'; - describe("edx.ccx.schedule.ScheduleView", function () { - var save_url = 'save_ccx'; - var view = null; - var data; + 'jquery', + 'underscore', + 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', + 'js/ccx/collection/schedule_collection', + 'js/ccx/view/ccx_schedule' +], function($, _, AjaxHelpers, ScheduleCollection, ScheduleView) { + 'use strict'; + describe('edx.ccx.schedule.ScheduleView', function() { + var saveUrl = 'save_ccx'; + var view = null; + var data; - beforeEach(function () { - loadFixtures("js/fixtures/ccx/schedule.html"); - $.fn.leanModal = function () { - return true; - }; + beforeEach(function() { + var scheduleCollection; + loadFixtures('js/fixtures/ccx/schedule.html'); + $.fn.leanModal = function() { + return true; + }; - data = [{ - 'category': 'chapter', - 'display_name': 'Introduction', - 'due': null, - 'start': null, - 'location': 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b', - 'hidden': true, - 'children': [ - { - "category": "sequential", - "display_name": "Demo Course Overview", - "due": null, - "start": null, - "location": "i4x://edX/DemoX/sequential/edx_introduction", - "hidden": true, - "children": [ - { - "category": "vertical", - "display_name": "Introduction: Video and Sequences", - "due": null, - "start": null, - "location": "i4x://edX/DemoX/vertical/vertical_0270f6de40fc", - "hidden": true - } - ] - } - ] - }]; - var scheduleCollection = new ScheduleCollection(data); - view = new ScheduleView({ - el: $("#ccx-schedule-container"), - saveCCXScheduleUrl: save_url, - collection: scheduleCollection - }); - view.render(); + data = [{ + 'category': 'chapter', + 'display_name': 'Introduction', + 'due': null, + 'start': null, + 'location': 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b', + 'hidden': true, + 'children': [ + { + 'category': 'sequential', + 'display_name': 'Demo Course Overview', + 'due': null, + 'start': null, + 'location': 'i4x://edX/DemoX/sequential/edx_introduction', + 'hidden': true, + 'children': [ + { + 'category': 'vertical', + 'display_name': 'Introduction: Video and Sequences', + 'due': null, + 'start': null, + 'location': 'i4x://edX/DemoX/vertical/vertical_0270f6de40fc', + 'hidden': true + } + ] + } + ] + }]; + scheduleCollection = new ScheduleCollection(data); + view = new ScheduleView({ + el: $('#ccx-schedule-container'), + saveCCXScheduleUrl: saveUrl, + collection: scheduleCollection }); + view.render(); + }); - it("verifies correct view setup", function () { - expect(view.scheduleRightContainer.chapters).toEqual(data); - expect(view.scheduleTreeView.chapters).toEqual([]); - }); + it('verifies correct view setup', function() { + expect(view.scheduleRightContainer.chapters).toEqual(data); + expect(view.scheduleTreeView.chapters).toEqual([]); + }); - it("finds a unit", function () { - var unit = view.collection.findUnit( - view.collection.toJSON(), 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' - ); - expect(unit).toEqual(data[0]); - }); + it('finds a unit', function() { + var unit = view.collection.findUnit( + view.collection.toJSON(), 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' + ); + expect(unit).toEqual(data[0]); + }); - it("hides a unit", function () { - var unit = view.collection.findUnit( - view.collection.toJSON(), - 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' - ); - unit.hidden = false; - view.collection.hide(unit); - expect(unit.hidden).toBe(true); - }); + it('hides a unit', function() { + var unit = view.collection.findUnit( + view.collection.toJSON(), + 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' + ); + unit.hidden = false; + view.collection.hide(unit); + expect(unit.hidden).toBe(true); + }); - it("shows a unit", function () { - var unit = view.collection.findUnit( - view.collection.toJSON(), - 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' - ); - view.collection.show(unit); - expect(unit.hidden).toBe(false); - }); + it('shows a unit', function() { + var unit = view.collection.findUnit( + view.collection.toJSON(), + 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' + ); + view.collection.show(unit); + expect(unit.hidden).toBe(false); + }); - it("make unit visible", function () { - view.collection.hideAllUnitFromScheduleTree(); - var unit = view.collection.findUnit( - view.collection.toJSON(), - 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' - ); + it('make unit visible', function() { + var unit; + view.collection.hideAllUnitFromScheduleTree(); + unit = view.collection.findUnit( + view.collection.toJSON(), + 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' + ); - expect(unit.hidden).toBe(true); + expect(unit.hidden).toBe(true); - view.collection.showUnitInScheduleTree( - 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b', - undefined, - undefined, - unit.start, - unit.due - ); + view.collection.showUnitInScheduleTree( + 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b', + undefined, + undefined, + unit.start, + unit.due + ); - unit = view.collection.findUnit( - view.collection.toJSON(), - 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' - ); + unit = view.collection.findUnit( + view.collection.toJSON(), + 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' + ); - expect(unit.hidden).toBe(false); - }); + expect(unit.hidden).toBe(false); + }); - it("adds all units to schedule", function () { - expect(view.scheduleTreeView.chapters).toEqual([]); - expect(view.scheduleRightContainer.chapters.length).toEqual(1); - $('#add-all').click(); - expect(view.scheduleTreeView.chapters.length).toEqual(1); - expect(view.scheduleRightContainer.chapters).toEqual([]); - }); + it('adds all units to schedule', function() { + expect(view.scheduleTreeView.chapters).toEqual([]); + expect(view.scheduleRightContainer.chapters.length).toEqual(1); + $('#add-all').click(); + expect(view.scheduleTreeView.chapters.length).toEqual(1); + expect(view.scheduleRightContainer.chapters).toEqual([]); + }); - it("selects a chapter and adds units to dropdown", function () { - expect(view.$("select#ccx_sequential").children('option').length).toEqual(0); - view.$("select#ccx_chapter").change(); - expect(view.$("select#ccx_sequential").prop('disabled')).toEqual(true); - var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; - view.$("select#ccx_chapter").val(val); - view.$("select#ccx_chapter").change(); - expect(view.$("select#ccx_chapter").val()).toEqual(val); - expect(view.$("select#ccx_chapter").prop('disabled')).toEqual(false); - expect(view.$("select#ccx_chapter").children('option').length).toEqual(2); - }); + it('selects a chapter and adds units to dropdown', function() { + var val; + expect(view.$('select#ccx_sequential').children('option').length).toEqual(0); + view.$('select#ccx_chapter').change(); + expect(view.$('select#ccx_sequential').prop('disabled')).toEqual(true); + val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; + view.$('select#ccx_chapter').val(val); + view.$('select#ccx_chapter').change(); + expect(view.$('select#ccx_chapter').val()).toEqual(val); + expect(view.$('select#ccx_chapter').prop('disabled')).toEqual(false); + expect(view.$('select#ccx_chapter').children('option').length).toEqual(2); + }); - it("selects a unit and adds sections to dropdown", function () { - var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; - view.$("select#ccx_chapter").val(val); - view.$("select#ccx_chapter").change(); - expect(view.$("select#ccx_vertical").children('option').length).toEqual(0); - view.$("select#ccx_sequential").change(); - expect(view.$("select#ccx_vertical").prop('disabled')).toEqual(true); - val = "i4x://edX/DemoX/sequential/edx_introduction"; - view.$("select#ccx_sequential").val(val); - view.$("select#ccx_sequential").change(); - expect(view.$("select#ccx_sequential").val()).toEqual(val); - expect(view.$("select#ccx_vertical").prop('disabled')).toEqual(false); - expect(view.$("select#ccx_vertical").children('option').length).toEqual(2); - }); + it('selects a unit and adds sections to dropdown', function() { + var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; + view.$('select#ccx_chapter').val(val); + view.$('select#ccx_chapter').change(); + expect(view.$('select#ccx_vertical').children('option').length).toEqual(0); + view.$('select#ccx_sequential').change(); + expect(view.$('select#ccx_vertical').prop('disabled')).toEqual(true); + val = 'i4x://edX/DemoX/sequential/edx_introduction'; + view.$('select#ccx_sequential').val(val); + view.$('select#ccx_sequential').change(); + expect(view.$('select#ccx_sequential').val()).toEqual(val); + expect(view.$('select#ccx_vertical').prop('disabled')).toEqual(false); + expect(view.$('select#ccx_vertical').children('option').length).toEqual(2); + }); - it("selects a section", function () { - var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; - view.$("select#ccx_chapter").val(val); - view.$("select#ccx_chapter").change(); - val = "i4x://edX/DemoX/sequential/edx_introduction"; - view.$("select#ccx_sequential").val(val); - view.$("select#ccx_sequential").change(); - val = "i4x://edX/DemoX/vertical/vertical_0270f6de40fc"; - view.$("select#ccx_vertical").val(val); - view.$("select#ccx_vertical").change(); - expect(view.$("select#ccx_vertical").val()).toEqual(val); - }); + it('selects a section', function() { + var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; + view.$('select#ccx_chapter').val(val); + view.$('select#ccx_chapter').change(); + val = 'i4x://edX/DemoX/sequential/edx_introduction'; + view.$('select#ccx_sequential').val(val); + view.$('select#ccx_sequential').change(); + val = 'i4x://edX/DemoX/vertical/vertical_0270f6de40fc'; + view.$('select#ccx_vertical').val(val); + view.$('select#ccx_vertical').change(); + expect(view.$('select#ccx_vertical').val()).toEqual(val); + }); - it("adds a unit", function () { - var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; - view.$("select#ccx_chapter").val(val); - view.$("select#ccx_chapter").change(); + it('adds a unit', function() { + var unit; + var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; + view.$('select#ccx_chapter').val(val); + view.$('select#ccx_chapter').change(); - val = "i4x://edX/DemoX/sequential/edx_introduction"; - view.$("select#ccx_sequential").val(val); - view.$("select#ccx_sequential").change(); + val = 'i4x://edX/DemoX/sequential/edx_introduction'; + view.$('select#ccx_sequential').val(val); + view.$('select#ccx_sequential').change(); - val = "i4x://edX/DemoX/vertical/vertical_0270f6de40fc"; - view.$("select#ccx_vertical").val(val); - view.$("select#ccx_vertical").change(); + val = 'i4x://edX/DemoX/vertical/vertical_0270f6de40fc'; + view.$('select#ccx_vertical').val(val); + view.$('select#ccx_vertical').change(); - var unit = view.collection.findUnit( - view.collection.toJSON(), - 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' - ); + unit = view.collection.findUnit( + view.collection.toJSON(), + 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' + ); - view.$('form#add-unit input[name=start_date]').val('2015-12-12'); - view.$('form#add-unit input[name=start_time]').val('10:00'); - view.$('form#add-unit input[name=due_date]').val('2015-12-12'); - view.$('form#add-unit input[name=due_time]').val('10:30'); - expect(unit.hidden).toBe(true); - $('#add-unit-button').click(); - unit = view.collection.findUnit( - view.collection.toJSON(), - 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' - ); - expect(unit.hidden).toBe(false); - }); + view.$('form#add-unit input[name=start_date]').val('2015-12-12'); + view.$('form#add-unit input[name=start_time]').val('10:00'); + view.$('form#add-unit input[name=due_date]').val('2015-12-12'); + view.$('form#add-unit input[name=due_time]').val('10:30'); - it("add unit when start date is greater the due date", function () { - var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; - view.$("select#ccx_chapter").val(val); - view.$("select#ccx_chapter").change(); - val = "i4x://edX/DemoX/sequential/edx_introduction"; - view.$("select#ccx_sequential").val(val); - view.$("select#ccx_sequential").change(); - val = "i4x://edX/DemoX/vertical/vertical_0270f6de40fc"; - view.$("select#ccx_vertical").val(val); - view.$("select#ccx_vertical").change(); - var unit = view.collection.findUnit( - view.collection.toJSON(), - 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' - ); - // start date is before due date - view.$('form#add-unit input[name=start_date]').val('2015-11-13'); - view.$('form#add-unit input[name=start_time]').val('10:45'); - view.$('form#add-unit input[name=due_date]').val('2015-11-12'); - view.$('form#add-unit input[name=due_time]').val('10:00'); + expect(unit.hidden).toBe(true); + $('#add-unit-button').click(); + unit = view.collection.findUnit( + view.collection.toJSON(), + 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' + ); + expect(unit.hidden).toBe(false); + }); - expect(unit.hidden).toBe(true); - $('#add-unit-button').click(); - // Assert unit is not added to schedule - expect(unit.hidden).toBe(true); - }); + it('add unit when start date is greater the due date', function() { + var unit; + var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; + view.$('select#ccx_chapter').val(val); + view.$('select#ccx_chapter').change(); + val = 'i4x://edX/DemoX/sequential/edx_introduction'; + view.$('select#ccx_sequential').val(val); + view.$('select#ccx_sequential').change(); + val = 'i4x://edX/DemoX/vertical/vertical_0270f6de40fc'; + view.$('select#ccx_vertical').val(val); + view.$('select#ccx_vertical').change(); + unit = view.collection.findUnit( + view.collection.toJSON(), + 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' + ); + // start date is before due date + view.$('form#add-unit input[name=start_date]').val('2015-11-13'); + view.$('form#add-unit input[name=start_time]').val('10:45'); + view.$('form#add-unit input[name=due_date]').val('2015-11-12'); + view.$('form#add-unit input[name=due_time]').val('10:00'); - it("add unit when start date is missing", function () { - var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; - view.$("select#ccx_chapter").val(val); - view.$("select#ccx_chapter").change(); - val = "i4x://edX/DemoX/sequential/edx_introduction"; - view.$("select#ccx_sequential").val(val); - view.$("select#ccx_sequential").change(); - val = "i4x://edX/DemoX/vertical/vertical_0270f6de40fc"; - view.$("select#ccx_vertical").val(val); - view.$("select#ccx_vertical").change(); - var unit = view.collection.findUnit( - view.collection.toJSON(), - 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' - ); - // start date is missing - view.$('form#add-unit input[name=start_date]').val(''); - view.$('form#add-unit input[name=start_time]').val(''); - view.$('form#add-unit input[name=due_date]').val('2015-12-12'); - view.$('form#add-unit input[name=due_time]').val('10:00'); + expect(unit.hidden).toBe(true); + $('#add-unit-button').click(); + // Assert unit is not added to schedule + expect(unit.hidden).toBe(true); + }); - expect(unit.hidden).toBe(true); - $('#add-unit-button').click(); - // Assert unit is not added to schedule - expect(unit.hidden).toBe(true); - }); + it('add unit when start date is missing', function() { + var unit; + var val = 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b'; + view.$('select#ccx_chapter').val(val); + view.$('select#ccx_chapter').change(); + val = 'i4x://edX/DemoX/sequential/edx_introduction'; + view.$('select#ccx_sequential').val(val); + view.$('select#ccx_sequential').change(); + val = 'i4x://edX/DemoX/vertical/vertical_0270f6de40fc'; + view.$('select#ccx_vertical').val(val); + view.$('select#ccx_vertical').change(); + unit = view.collection.findUnit( + view.collection.toJSON(), + 'i4x://edX/DemoX/chapter/d8a6192ade314473a78242dfeedfbf5b' + ); + // start date is missing + view.$('form#add-unit input[name=start_date]').val(''); + view.$('form#add-unit input[name=start_time]').val(''); + view.$('form#add-unit input[name=due_date]').val('2015-12-12'); + view.$('form#add-unit input[name=due_time]').val('10:00'); - it("gets a datetime string from date and time fields", function () { - view.$('form#add-unit input[name=start_date]').val('2015-12-12'); - view.$('form#add-unit input[name=start_time]').val('10:45'); - expect($('form#add-unit input[name=start_date]')).toHaveValue('2015-12-12'); - expect($('form#add-unit input[name=start_time]')).toHaveValue('10:45'); - }); + expect(unit.hidden).toBe(true); + $('#add-unit-button').click(); + // Assert unit is not added to schedule + expect(unit.hidden).toBe(true); + }); - it("sets date and time fields from datetime string", function () { - $('form#add-unit input[name=start_date]').val('2015-12-12'); - $('form#add-unit input[name=start_time]').val('10:45'); - var datetime = view.scheduleRightContainer.getDateTime('start'); - expect(datetime).toBe('2015-12-12 10:45'); - }); + it('gets a datetime string from date and time fields', function() { + view.$('form#add-unit input[name=start_date]').val('2015-12-12'); + view.$('form#add-unit input[name=start_time]').val('10:45'); + expect($('form#add-unit input[name=start_date]')).toHaveValue('2015-12-12'); + expect($('form#add-unit input[name=start_time]')).toHaveValue('10:45'); + }); - it("saves schedule changes", function () { - var requests = AjaxHelpers.requests(this); - view.saveSchedule(); - expect(requests.length).toEqual(1); - AjaxHelpers.expectJsonRequest( - requests, - 'POST', - 'save_ccx', - view.collection.toJSON() - ); - AjaxHelpers.respondWithJson(requests, { - data: view.collection.toJSON() - }); - expect($('#ajax-error')).toHaveCss({display: 'none'}); - }); + it('sets date and time fields from datetime string', function() { + var datetime; + $('form#add-unit input[name=start_date]').val('2015-12-12'); + $('form#add-unit input[name=start_time]').val('10:45'); + datetime = view.scheduleRightContainer.getDateTime('start'); + expect(datetime).toBe('2015-12-12 10:45'); + }); - it("displays an error if the sync fails", function () { - var requests = AjaxHelpers.requests(this); - view.saveSchedule(); - requests[0].respond(500); - expect($('#ajax-error')).toHaveCss({display: 'block'}); + it('saves schedule changes', function() { + var requests = AjaxHelpers.requests(this); + view.saveSchedule(); + expect(requests.length).toEqual(1); + AjaxHelpers.expectJsonRequest( + requests, + 'POST', + 'save_ccx', + view.collection.toJSON() + ); + AjaxHelpers.respondWithJson(requests, { + data: view.collection.toJSON() }); + expect($('#ajax-error')).toHaveCss({display: 'none'}); + }); + + it('displays an error if the sync fails', function() { + var requests = AjaxHelpers.requests(this); + view.saveSchedule(); + requests[0].respond(500); + expect($('#ajax-error')).toHaveCss({display: 'block'}); }); - } -); + }); +}); diff --git a/lms/static/lms/js/require-config.js b/lms/static/lms/js/require-config.js index be9a896634b1..370db537072b 100644 --- a/lms/static/lms/js/require-config.js +++ b/lms/static/lms/js/require-config.js @@ -82,7 +82,7 @@ 'string_utils': 'js/src/string_utils', 'utility': 'js/src/utility', 'draggabilly': 'js/vendor/draggabilly', - "jquery.timepicker": 'xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker', + 'jquery.timepicker': 'xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker', // Files needed by OVA 'annotator': 'js/vendor/ova/annotator-full',