diff --git a/cms/static/js/models/course_relative.js b/cms/static/js/models/course_relative.js index 5c42f4ce80..c33339ff48 100644 --- a/cms/static/js/models/course_relative.js +++ b/cms/static/js/models/course_relative.js @@ -1,4 +1,4 @@ -CMS.Models.Location = Backbone.Models.extend({ +CMS.Models.Location = Backbone.Model.extend({ defaults: { tag: "", org: "", @@ -14,29 +14,29 @@ CMS.Models.Location = Backbone.Models.extend({ (overrides['category'] ? overrides['category'] : this.get('category')) + "/" + (overrides['name'] ? overrides['name'] : this.get('name')) + "/"; }, - _tagPattern = /[^:]+/g, - _fieldPattern = new RegExp('[^/]+','g'), + _tagPattern : /[^:]+/g, + _fieldPattern : new RegExp('[^/]+','g'), parse: function(payload) { - if (payload instanceof Array) { + if (_.isArray(payload)) { return { tag: payload[0], - name: payload[1], + org: payload[1], course: payload[2], category: payload[3], name: payload[4] } } - else if (payload instanceof String) { + else if (_.isString(payload)) { var foundTag = this._tagPattern.exec(payload); if (foundTag) { - this._fieldPattern.lastIndex = this._tagPattern.lastIndex; + this._fieldPattern.lastIndex = this._tagPattern.lastIndex + 1; // skip over the colon return { - tag: foundTag, - name: this._fieldPattern.exec(payload), - course: this._fieldPattern.exec(payload), - category: this._fieldPattern.exec(payload), - name: this._fieldPattern.exec(payload) + tag: foundTag[0], + org: this._fieldPattern.exec(payload)[0], + course: this._fieldPattern.exec(payload)[0], + category: this._fieldPattern.exec(payload)[0], + name: this._fieldPattern.exec(payload)[0] } } else return null; @@ -47,13 +47,13 @@ CMS.Models.Location = Backbone.Models.extend({ } }); -CMS.Models.CourseRelative = Backbone.Models.extend({ +CMS.Models.CourseRelative = Backbone.Model.extend({ defaults: { course_location : null, // must never be null, but here to doc the field idx : null // the index making it unique in the containing collection (no implied sort) } }); -CMS.Models.CourseRelativeCollection = Backbone.Collections.extend({ - model : CourseRelative +CMS.Models.CourseRelativeCollection = Backbone.Collection.extend({ + model : CMS.Models.CourseRelative }); \ No newline at end of file diff --git a/cms/static/js/models/settings/course_details.js b/cms/static/js/models/settings/course_details.js new file mode 100644 index 0000000000..3ae4a86f90 --- /dev/null +++ b/cms/static/js/models/settings/course_details.js @@ -0,0 +1,40 @@ +if (!CMS.Models['Settings']) CMS.Models.Settings = new Object(); + +CMS.Models.Settings.CourseDetails = Backbone.Model.extend({ + defaults: { + location : null, // the course's Location model, required + start_date: null, // maps to 'start' + end_date: null, // maps to 'end' + enrollment_start: null, + enrollment_end: null, + syllabus: null, + overview: "", + intro_video: null, + effort: null // an int or null + }, + + // When init'g from html script, ensure you pass {parse: true} as an option (2nd arg to reset) + parse: function(attributes) { + if (attributes['course_location']) { + attributes.location = new CMS.Models.Location(attributes.course_location, {parse:true}); + } + if (attributes['start_date']) { + attributes.start_date = new Date(attributes.start_date); + } + if (attributes['end_date']) { + attributes.end_date = new Date(attributes.end_date); + } + if (attributes['enrollment_start']) { + attributes.enrollment_start = new Date(attributes.enrollment_start); + } + if (attributes['enrollment_end']) { + attributes.enrollment_end = new Date(attributes.enrollment_end); + } + return attributes; + }, + + urlRoot: function() { + var location = this.get('location'); + return '/' + location.get('org') + "/" + location.get('course') + '/settings/' + location.get('name') + '/section/details'; + } +}); diff --git a/cms/static/js/models/settings/course_detais.js b/cms/static/js/models/settings/course_detais.js deleted file mode 100644 index c725ed46a2..0000000000 --- a/cms/static/js/models/settings/course_detais.js +++ /dev/null @@ -1,25 +0,0 @@ -CMS.Models.Settings.CourseDetails = Backbone.Models.extend({ - defaults: { - location : null, // the course's Location model, required - start_date: null, // maps to 'start' - end_date: null, // maps to 'end' - enrollment_start: null, - enrollment_end: null, - syllabus: null, - overview: "", - intro_video: null, - effort: null # an int or null - }, - - // When init'g from html script, ensure you pass {parse: true} as an option (2nd arg to reset) - parse: function(attributes) { - if (attributes['location']) { - attributes.location = new CMS.Models.Location(attributes.location); - }; - }, - - urlRoot: function() { - var location = this.get('location'); - return '/' + location.get('org') + "/" + location.get('course') + '/settings/' + location.get('name') + '/section/details'; - } -}); diff --git a/cms/static/js/models/settings/course_settings.js b/cms/static/js/models/settings/course_settings.js index c6959a8693..de4468c00b 100644 --- a/cms/static/js/models/settings/course_settings.js +++ b/cms/static/js/models/settings/course_settings.js @@ -1,3 +1,4 @@ +if (!CMS.Models['Settings']) CMS.Models.Settings = new Object(); CMS.Models.Settings.CourseSettings = Backbone.Model.extend({ // a container for the models representing the n possible tabbed states defaults: { diff --git a/cms/static/js/views/settings/main_settings_view.js b/cms/static/js/views/settings/main_settings_view.js index 5a862dd5ef..b4019e12ea 100644 --- a/cms/static/js/views/settings/main_settings_view.js +++ b/cms/static/js/views/settings/main_settings_view.js @@ -1,3 +1,5 @@ +if (!CMS.Views['Settings']) CMS.Views.Settings = new Object(); + CMS.Views.Settings.Main = Backbone.View.extend({ // Model class is CMS.Models.Settings.CourseSettings // allow navigation between the tabs @@ -6,7 +8,7 @@ CMS.Views.Settings.Main = Backbone.View.extend({ }, currentTab: null, - subviews: {}, # indexed by tab name + subviews: {}, // indexed by tab name initialize: function() { // load templates @@ -31,8 +33,7 @@ CMS.Views.Settings.Main = Backbone.View.extend({ this.subviews[this.currentTab].render(); }); } - } - else this.callRenderFunction(); + else this.subviews[this.currentTab].render(); return this; }, @@ -42,7 +43,7 @@ CMS.Views.Settings.Main = Backbone.View.extend({ case 'details': return new CMS.Views.Settings.Details({ el: this.$el.find('.settings-' + this.currentTab), - model: this.model.get(this.currentTab); + model: this.model.get(this.currentTab) }); break; case 'faculty': @@ -72,6 +73,7 @@ CMS.Views.Settings.Details = Backbone.View.extend({ // Model class is CMS.Models.Settings.CourseDetails events : { "blur input" : "updateModel", + "blur textarea" : "updateModel", 'click .remove-course-syllabus' : "removeSyllabus", 'click .new-course-syllabus' : 'assetSyllabus', 'click .remove-course-introduction-video' : "removeVideo", @@ -80,15 +82,13 @@ CMS.Views.Settings.Details = Backbone.View.extend({ initialize : function() { // TODO move the html frag to a loaded asset this.fileAnchorTemplate = _.template(' 📄<%= filename %>'); - // Save every change as it occurs. This may be too noisy!!! If not every change, then need sophisticated logic. - this.model.on('change', this.model.save); }, render: function() { - if (this.model.has('start_date')) this.$el.find('#course-start-date').datepicker('setDate', this.model.get('start_date')); - if (this.model.has('end_date')) this.$el.find('#course-end-date').datepicker('setDate', this.model.get('end_date')); - if (this.model.has('enrollment_start')) this.$el.find('#course-enrollment-start').datepicker('setDate', this.model.get('enrollment_start')); - if (this.model.has('enrollment_end')) this.$el.find('#course-enrollment-end').datepicker('setDate', this.model.get('enrollment_end')); + this.setupDatePicker('#course-start-date', 'start_date'); + this.setupDatePicker('#course-end-date', 'end_date'); + this.setupDatePicker('#course-enrollment-start-date', 'enrollment_start'); + this.setupDatePicker('#course-enrollment-end-date', 'enrollment_end'); if (this.model.has('syllabus')) { this.$el.find('.current-course-syllabus .doc-filename').html( @@ -97,46 +97,58 @@ CMS.Views.Settings.Details = Backbone.View.extend({ filename: 'syllabus'})); this.$el.find('.remove-course-syllabus').show(); } - else this.$el.find('.remove-course-syllabus').hide(); + else { + this.$el.find('.current-course-syllabus .doc-filename').html(""); + this.$el.find('.remove-course-syllabus').hide(); + } - if (this.model.has('overview')) - this.$el.find('#course-overview').text(this.model.get('overview')); + this.$el.find('#course-overview').val(this.model.get('overview')); + this.$el.find('.current-course-introduction-video iframe').attr('src', this.model.get('intro_video')); if (this.model.has('intro_video')) { - this.$el.find('.current-course-introduction-video iframe').attr('src', this.model.get('intro_video')); this.$el.find('.remove-course-introduction-video').show(); } else this.$el.find('.remove-course-introduction-video').hide(); + + this.$el.find("#course-effort").val(this.model.get('effort')); + + return this; + }, + + setupDatePicker : function(elementName, fieldName) { + var cacheModel = this.model; + var picker = this.$el.find(elementName); + picker.datepicker({ onSelect : function(newVal) { + cacheModel.save(fieldName, new Date(newVal)); + }}); + picker.datepicker('setDate', this.model.get(fieldName)); }, updateModel: function(event) { // figure out which field switch (event.currentTarget.id) { - case 'course-start-date': - var val = $(event.currentTarget).datepicker('getDate'); - this.model.set('start_date', val); - break; + case 'course-start-date': // handled via onSelect method case 'course-end-date': - this.model.set('end_date', $(event.currentTarget).datepicker('getDate')); - break; case 'course-enrollment-start-date': - this.model.set('enrollment_start', $(event.currentTarget).datepicker('getDate')); - break; case 'course-enrollment-end-date': - this.model.set('enrollment_end', $(event.currentTarget).datepicker('getDate')); break; case 'course-overview': - this.model.set('overview', $(event.currentTarget).text()); + this.model.save('overview', $(event.currentTarget).val()); break; + case 'course-effort': + this.model.save('effort', $(event.currentTarget).val()); + break; + default: break; } + }, removeSyllabus: function() { - if (this.model.has('syllabus')) this.model.set({'syllabus': null}); + if (this.model.has('syllabus')) this.model.save({'syllabus': null}); }, assetSyllabus : function() { @@ -144,7 +156,7 @@ CMS.Views.Settings.Details = Backbone.View.extend({ }, removeVideo: function() { - if (this.model.has('intro_video')) this.model.set({'intro_video': null}); + if (this.model.has('intro_video')) this.model.save({'intro_video': null}); }, assetVideo : function() { diff --git a/cms/templates/settings.html b/cms/templates/settings.html index fc58674847..9d5514c90d 100644 --- a/cms/templates/settings.html +++ b/cms/templates/settings.html @@ -3,6 +3,10 @@ <%block name="title">Settings%block> <%namespace name='static' file='static_content.html'/> +<%! +from contentstore import utils +%> + <%block name="jsextra"> @@ -24,9 +28,9 @@ details: new CMS.Models.Settings.CourseDetails(${course_details|n},{parse:true}) }); - var editor = new CMS.Views.CourseInfoEdit({ + var editor = new CMS.Views.Settings.Main({ el: $('.main-wrapper'), - model : settingsModel) + model : settingsModel }); $('.set-date').datepicker({ 'dateFormat': 'm/d/yy' }); @@ -147,7 +151,7 @@