Commit c0da6e42 by Don Mitchell

Details done except for syllabus

parent a48a392e
...@@ -647,8 +647,6 @@ def unpublish_unit(request): ...@@ -647,8 +647,6 @@ def unpublish_unit(request):
return HttpResponse() return HttpResponse()
@login_required @login_required
@expect_json @expect_json
def clone_item(request): def clone_item(request):
...@@ -952,11 +950,13 @@ def get_course_settings(request, org, course, name): ...@@ -952,11 +950,13 @@ def get_course_settings(request, org, course, name):
raise PermissionDenied() raise PermissionDenied()
course_module = modulestore().get_item(location) course_module = modulestore().get_item(location)
course_details = CourseDetails.fetch(location)
return render_to_response('settings.html', { return render_to_response('settings.html', {
'active_tab': 'settings-tab', 'active_tab': 'settings-tab',
'context_course': course_module, 'context_course': course_module,
'course_details' : json.dumps(CourseDetails.fetch(location), cls=CourseDetailsEncoder) 'course_details' : json.dumps(course_details, cls=CourseDetailsEncoder),
'video_editor_html' : preview_component(request, course_details.intro_video_loc)
}) })
@expect_json @expect_json
......
...@@ -36,5 +36,72 @@ CMS.Models.Settings.CourseDetails = Backbone.Model.extend({ ...@@ -36,5 +36,72 @@ CMS.Models.Settings.CourseDetails = Backbone.Model.extend({
urlRoot: function() { urlRoot: function() {
var location = this.get('location'); var location = this.get('location');
return '/' + location.get('org') + "/" + location.get('course') + '/settings/' + location.get('name') + '/section/details'; return '/' + location.get('org') + "/" + location.get('course') + '/settings/' + location.get('name') + '/section/details';
},
_videoprefix : /\s*<video\s*youtube="/g,
_videospeedparse : /\d+\.?\d*(?=:)/g,
_videokeyparse : /([^,\/]+)/g,
_videonosuffix : /[^\"]+/g,
_getNextMatch : function (regex, string, cursor) {
regex.lastIndex = cursor;
return regex.exec(string);
},
// the whole string for editing
getVideoSource: function() {
if (this.get('intro_video')) {
var cursor = 0;
var videostring = this.get('intro_video');
this._getNextMatch(this._videoprefix, videostring, cursor);
cursor = this._videoprefix.lastIndex;
return this._getNextMatch(this._videonosuffix, videostring, cursor);
}
else return "";
},
// the source closest to 1.0 speed
videosourceSample: function() {
if (this.get('intro_video')) {
var cursor = 0;
var videostring = this.get('intro_video');
this._getNextMatch(this._videoprefix, videostring, cursor);
cursor = this._videoprefix.lastIndex;
// parse from [speed:id,/s?]* to find 1.0 or take first
var parsedspeed = this._getNextMatch(this._videospeedparse, videostring, cursor);
var bestkey;
if (parsedspeed) {
cursor = this._videospeedparse.lastIndex + 1;
var bestspeed = Number(parsedspeed);
bestkey = this._getNextMatch(this._videokeyparse, videostring, cursor);
cursor = this._videokeyparse.lastIndex + 1;
while (cursor < videostring.length && bestspeed != 1.0) {
parsedspeed = this._getNextMatch(this._videospeedparse, videostring, cursor);
cursor = this._videospeedparse.lastIndex + 1;
if (Math.abs(Number(parsedspeed) - 1.0) < Math.abs(bestspeed - 1.0)) {
bestspeed = Number(parsedspeed);
bestkey = this._getNextMatch(this._videokeyparse, videostring, cursor);
}
else this._getNextMatch(this._videokeyparse, videostring, cursor);
cursor = this._videokeyparse.lastIndex + 1;
}
}
else {
bestkey = this._getNextMatch(this._videokeyparse, videostring, cursor);
}
if (bestkey) {
// WTF? for some reason bestkey is an array [key, key] (same one repeated)
if (_.isArray(bestkey)) bestkey = bestkey[0];
return "http://www.youtube.com/embed/" + bestkey;
}
else return "";
}
},
save_videosource: function(newsource) {
// 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
if (newsource == null) this.save({'intro_video': null});
else if (this._getNextMatch(this._videoprefix, newsource, 0)) this.save('intro_video', newsource);
else this.save('intro_video', '<video youtube="' + newsource + '"/>');
return this.videosourceSample();
} }
}); });
...@@ -82,8 +82,7 @@ CMS.Views.Settings.Details = Backbone.View.extend({ ...@@ -82,8 +82,7 @@ CMS.Views.Settings.Details = Backbone.View.extend({
"blur textarea" : "updateModel", "blur textarea" : "updateModel",
'click .remove-course-syllabus' : "removeSyllabus", 'click .remove-course-syllabus' : "removeSyllabus",
'click .new-course-syllabus' : 'assetSyllabus', 'click .new-course-syllabus' : 'assetSyllabus',
'click .remove-course-introduction-video' : "removeVideo", 'click .remove-course-introduction-video' : "removeVideo"
'click .new-course-introduction-video' : 'assetVideo',
}, },
initialize : function() { initialize : function() {
// TODO move the html frag to a loaded asset // TODO move the html frag to a loaded asset
...@@ -110,9 +109,10 @@ CMS.Views.Settings.Details = Backbone.View.extend({ ...@@ -110,9 +109,10 @@ CMS.Views.Settings.Details = Backbone.View.extend({
this.$el.find('#course-overview').val(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')); this.$el.find('.current-course-introduction-video iframe').attr('src', this.model.videosourceSample());
if (this.model.has('intro_video')) { if (this.model.has('intro_video')) {
this.$el.find('.remove-course-introduction-video').show(); this.$el.find('.remove-course-introduction-video').show();
this.$el.find('#course-introduction-video').val(this.model.getVideoSource());
} }
else this.$el.find('.remove-course-introduction-video').hide(); else this.$el.find('.remove-course-introduction-video').hide();
...@@ -158,6 +158,10 @@ CMS.Views.Settings.Details = Backbone.View.extend({ ...@@ -158,6 +158,10 @@ CMS.Views.Settings.Details = Backbone.View.extend({
case 'course-effort': case 'course-effort':
this.model.save('effort', $(event.currentTarget).val()); this.model.save('effort', $(event.currentTarget).val());
break; break;
case 'course-introduction-video':
var previewsource = this.model.save_videosource($(event.currentTarget).val());
this.$el.find(".current-course-introduction-video iframe").attr("src", previewsource);
break
default: default:
break; break;
...@@ -174,10 +178,11 @@ CMS.Views.Settings.Details = Backbone.View.extend({ ...@@ -174,10 +178,11 @@ CMS.Views.Settings.Details = Backbone.View.extend({
}, },
removeVideo: function() { removeVideo: function() {
if (this.model.has('intro_video')) this.model.save({'intro_video': null}); if (this.model.has('intro_video')) {
}, this.model.save_videosource(null);
this.$el.find(".current-course-introduction-video iframe").attr("src", "");
assetVideo : function() { this.$el.find('#course-introduction-video').val("");
// TODO implement }
} }
}); });
\ No newline at end of file
...@@ -339,9 +339,7 @@ from contentstore import utils ...@@ -339,9 +339,7 @@ from contentstore import utils
</div> </div>
<div class="input"> <div class="input">
<a href="#" class="new-item new-course-introduction-video add-video-data" id="course-introduction-video"> <input type="text" class="new-item new-course-introduction-video add-video-data" id="course-introduction-video" value="" placeholder="speed:id,speed:id" autocomplete="off">
<span class="upload-icon"></span>Upload Video
</a>
<span class="tip tip-inline">Video restrictions go here</span> <span class="tip tip-inline">Video restrictions go here</span>
</div> </div>
</div> </div>
......
...@@ -17,6 +17,7 @@ class CourseDetails: ...@@ -17,6 +17,7 @@ class CourseDetails:
self.syllabus = None # a pdf file asset self.syllabus = None # a pdf file asset
self.overview = "" # html to render as the overview self.overview = "" # html to render as the overview
self.intro_video = None # a video pointer self.intro_video = None # a video pointer
self.intro_video_loc = None # a video pointer
self.effort = None # int hours/week self.effort = None # int hours/week
@classmethod @classmethod
...@@ -57,6 +58,7 @@ class CourseDetails: ...@@ -57,6 +58,7 @@ class CourseDetails:
temploc = temploc._replace(name='video') temploc = temploc._replace(name='video')
try: try:
course.intro_video = get_modulestore(temploc).get_item(temploc).definition['data'] course.intro_video = get_modulestore(temploc).get_item(temploc).definition['data']
course.intro_video_loc = temploc
except ItemNotFoundError: except ItemNotFoundError:
pass pass
......
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