Merge remote-tracking branch 'origin/feature/cale/cms-master' into
feature/dhm/cms-settings Conflicts: cms/djangoapps/contentstore/course_info_model.py cms/djangoapps/contentstore/views.py cms/static/js/models/course_info.js cms/static/js/template_loader.js cms/static/js/views/course_info_edit.js cms/templates/base.html cms/templates/course_info.html cms/urls.py
This commit is contained in:
19
cms/static/client_templates/course_info_handouts.html
Normal file
19
cms/static/client_templates/course_info_handouts.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<a href="#" class="edit-button"><span class="edit-icon"></span>Edit</a>
|
||||
|
||||
<h2>Course Handouts</h2>
|
||||
<%if (model.get('data') != null) { %>
|
||||
<div class="handouts-content">
|
||||
<%= model.get('data') %>
|
||||
</div>
|
||||
<% } else {%>
|
||||
<p>You have no handouts defined</p>
|
||||
<% } %>
|
||||
<form class="edit-handouts-form" style="display: block;">
|
||||
<div class="row">
|
||||
<textarea class="handouts-content-editor text-editor"></textarea>
|
||||
</div>
|
||||
<div class="row">
|
||||
<a href="#" class="save-button">Save</a>
|
||||
<a href="#" class="cancel-button">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
29
cms/static/client_templates/course_info_update.html
Normal file
29
cms/static/client_templates/course_info_update.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<li name="<%- updateModel.cid %>">
|
||||
<!-- FIXME what style should we use for initially hidden? --> <!-- TODO decide whether this should use codemirror -->
|
||||
<form class="new-update-form">
|
||||
<div class="row">
|
||||
<label class="inline-label">Date:</label>
|
||||
<!-- TODO replace w/ date widget and actual date (problem is that persisted version is "Month day" not an actual date obj -->
|
||||
<input type="text" class="date" value="<%= updateModel.get('date') %>">
|
||||
</div>
|
||||
<div class="row">
|
||||
<textarea class="new-update-content text-editor"><%= updateModel.get('content') %></textarea>
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- cid rather than id b/c new ones have cid's not id's -->
|
||||
<a href="#" class="save-button" name="<%= updateModel.cid %>">Save</a>
|
||||
<a href="#" class="cancel-button" name="<%= updateModel.cid %>">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
<div class="post-preview">
|
||||
<div class="post-actions">
|
||||
<a href="#" class="edit-button" name="<%- updateModel.cid %>"><span class="edit-icon"></span>Edit</a>
|
||||
<a href="#" class="delete-button" name="<%- updateModel.cid %>"><span class="delete-icon"></span>Delete</a>
|
||||
</div>
|
||||
<h2>
|
||||
<span class="calendar-icon"></span><span class="date-display"><%=
|
||||
updateModel.get('date') %></span>
|
||||
</h2>
|
||||
<div class="update-contents"><%= updateModel.get('content') %></div>
|
||||
</div>
|
||||
</li>
|
||||
14
cms/static/client_templates/load_templates.html
Normal file
14
cms/static/client_templates/load_templates.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!-- In order to enable better debugging of templates, put them in
|
||||
the script tag section.
|
||||
TODO add lazy load fn to load templates as needed (called
|
||||
from backbone view initialize to set this.template of the view)
|
||||
-->
|
||||
|
||||
<%block name="jsextra">
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
// How do I load an html file server side so I can
|
||||
// Precompiling your templates can be a big help when debugging errors you can't reproduce. This is because precompiled templates can provide line numbers and a stack trace, something that is not possible when compiling templates on the client. The source property is available on the compiled template function for easy precompilation.
|
||||
// <script>CMS.course_info_update = <%= _.template(jstText).source %>;</script>
|
||||
|
||||
</script>
|
||||
</%block>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 970 B After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 2.9 KiB |
BIN
cms/static/img/plus-icon-white.png
Normal file
BIN
cms/static/img/plus-icon-white.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 951 B |
@@ -11,6 +11,11 @@ $(document).ready(function() {
|
||||
$body = $('body');
|
||||
$modal = $('.history-modal');
|
||||
$modalCover = $('<div class="modal-cover">');
|
||||
// cdodge: this looks funny, but on AWS instances, this base.js get's wrapped in a separate scope as part of Django static
|
||||
// pipelining (note, this doesn't happen on local runtimes). So if we set it on window, when we can access it from other
|
||||
// scopes (namely the course-info tab)
|
||||
window.$modalCover = $modalCover;
|
||||
|
||||
$body.append($modalCover);
|
||||
$newComponentItem = $('.new-component-item');
|
||||
$newComponentTypePicker = $('.new-component');
|
||||
@@ -93,7 +98,7 @@ $(document).ready(function() {
|
||||
// section name editing
|
||||
$('.section-name').bind('click', editSectionName);
|
||||
$('.edit-section-name-cancel').bind('click', cancelEditSectionName);
|
||||
$('.edit-section-name-save').bind('click', saveEditSectionName);
|
||||
// $('.edit-section-name-save').bind('click', saveEditSectionName);
|
||||
|
||||
// section date setting
|
||||
$('.set-publish-date').bind('click', setSectionScheduleDate);
|
||||
@@ -585,33 +590,44 @@ function hideToastMessage(e) {
|
||||
$(this).closest('.toast-notification').remove();
|
||||
}
|
||||
|
||||
function addNewSection(e) {
|
||||
function addNewSection(e, isTemplate) {
|
||||
e.preventDefault();
|
||||
|
||||
var $newSection = $($('#new-section-template').html());
|
||||
var $cancelButton = $newSection.find('.new-section-name-cancel');
|
||||
$('.new-courseware-section-button').after($newSection);
|
||||
$newSection.find('.new-section-name').focus().select();
|
||||
$newSection.find('.new-section-name-save').bind('click', saveNewSection);
|
||||
$newSection.find('.new-section-name-cancel').bind('click', cancelNewSection);
|
||||
$newSection.find('.section-name-form').bind('submit', saveNewSection);
|
||||
$cancelButton.bind('click', cancelNewSection);
|
||||
$body.bind('keyup', { $cancelButton: $cancelButton }, checkForCancel);
|
||||
}
|
||||
|
||||
function checkForCancel(e) {
|
||||
if(e.which == 27) {
|
||||
$body.unbind('keyup', checkForCancel);
|
||||
e.data.$cancelButton.click();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function saveNewSection(e) {
|
||||
e.preventDefault();
|
||||
|
||||
parent = $(this).data('parent');
|
||||
template = $(this).data('template');
|
||||
var $saveButton = $(this).find('.new-section-name-save');
|
||||
var parent = $saveButton.data('parent');
|
||||
var template = $saveButton.data('template');
|
||||
var display_name = $(this).find('.new-section-name').val();
|
||||
|
||||
display_name = $(this).prev('.new-section-name').val();
|
||||
|
||||
$.post('/clone_item',
|
||||
{'parent_location' : parent,
|
||||
'template' : template,
|
||||
'display_name': display_name,
|
||||
},
|
||||
function(data) {
|
||||
$.post('/clone_item', {
|
||||
'parent_location' : parent,
|
||||
'template' : template,
|
||||
'display_name': display_name,
|
||||
},
|
||||
function(data) {
|
||||
if (data.id != undefined)
|
||||
location.reload();
|
||||
});
|
||||
location.reload();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function cancelNewSection(e) {
|
||||
@@ -619,44 +635,44 @@ function cancelNewSection(e) {
|
||||
$(this).parents('section.new-section').remove();
|
||||
}
|
||||
|
||||
|
||||
function addNewCourse(e) {
|
||||
e.preventDefault();
|
||||
var $newCourse = $($('#new-course-template').html());
|
||||
var $cancelButton = $newCourse.find('.new-course-cancel');
|
||||
$('.new-course-button').after($newCourse);
|
||||
$newCourse.find('.new-course-name').focus().select();
|
||||
$newCourse.find('.new-course-save').bind('click', saveNewCourse);
|
||||
$newCourse.find('.new-course-cancel').bind('click', cancelNewCourse);
|
||||
$newCourse.find('form').bind('submit', saveNewCourse);
|
||||
$cancelButton.bind('click', cancelNewCourse);
|
||||
$body.bind('keyup', { $cancelButton: $cancelButton }, checkForCancel);
|
||||
}
|
||||
|
||||
function saveNewCourse(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $newCourse = $(this).closest('.new-course');
|
||||
|
||||
template = $(this).data('template');
|
||||
|
||||
org = $newCourse.find('.new-course-org').val();
|
||||
number = $newCourse.find('.new-course-number').val();
|
||||
display_name = $newCourse.find('.new-course-name').val();
|
||||
var template = $(this).find('.new-course-save').data('template');
|
||||
var org = $newCourse.find('.new-course-org').val();
|
||||
var number = $newCourse.find('.new-course-number').val();
|
||||
var display_name = $newCourse.find('.new-course-name').val();
|
||||
|
||||
if (org == '' || number == '' || display_name == ''){
|
||||
alert('You must specify all fields in order to create a new course.');
|
||||
return;
|
||||
}
|
||||
|
||||
$.post('/create_new_course',
|
||||
{ 'template' : template,
|
||||
'org' : org,
|
||||
'number' : number,
|
||||
'display_name': display_name,
|
||||
},
|
||||
function(data) {
|
||||
if (data.id != undefined)
|
||||
location.reload();
|
||||
else if (data.ErrMsg != undefined)
|
||||
$.post('/create_new_course', {
|
||||
'template' : template,
|
||||
'org' : org,
|
||||
'number' : number,
|
||||
'display_name': display_name,
|
||||
},
|
||||
function(data) {
|
||||
if (data.id != undefined) {
|
||||
window.location = '/' + data.id.replace(/.*:\/\//, '');
|
||||
} else if (data.ErrMsg != undefined) {
|
||||
alert(data.ErrMsg);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function cancelNewCourse(e) {
|
||||
@@ -672,35 +688,37 @@ function addNewSubsection(e) {
|
||||
$section.find('.new-subsection-name-input').focus().select();
|
||||
|
||||
var $saveButton = $newSubsection.find('.new-subsection-name-save');
|
||||
$saveButton.bind('click', saveNewSubsection);
|
||||
var $cancelButton = $newSubsection.find('.new-subsection-name-cancel');
|
||||
|
||||
parent = $(this).parents("section.branch").data("id");
|
||||
var parent = $(this).parents("section.branch").data("id");
|
||||
|
||||
$saveButton.data('parent', parent)
|
||||
$saveButton.data('template', $(this).data('template'));
|
||||
|
||||
$newSubsection.find('.new-subsection-name-cancel').bind('click', cancelNewSubsection);
|
||||
$newSubsection.find('.new-subsection-form').bind('submit', saveNewSubsection);
|
||||
$cancelButton.bind('click', cancelNewSubsection);
|
||||
$body.bind('keyup', { $cancelButton: $cancelButton }, checkForCancel);
|
||||
}
|
||||
|
||||
function saveNewSubsection(e) {
|
||||
e.preventDefault();
|
||||
|
||||
parent = $(this).data('parent');
|
||||
template = $(this).data('template');
|
||||
var parent = $(this).find('.new-subsection-name-save').data('parent');
|
||||
var template = $(this).find('.new-subsection-name-save').data('template');
|
||||
|
||||
var display_name = $(this).find('.new-subsection-name-input').val();
|
||||
|
||||
display_name = $(this).prev('.subsection-name').find('.new-subsection-name-input').val()
|
||||
|
||||
$.post('/clone_item',
|
||||
{'parent_location' : parent,
|
||||
'template' : template,
|
||||
'display_name': display_name,
|
||||
},
|
||||
function(data) {
|
||||
$.post('/clone_item', {
|
||||
'parent_location' : parent,
|
||||
'template' : template,
|
||||
'display_name': display_name
|
||||
},
|
||||
function(data) {
|
||||
if (data.id != undefined) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function cancelNewSubsection(e) {
|
||||
@@ -710,22 +728,30 @@ function cancelNewSubsection(e) {
|
||||
|
||||
function editSectionName(e) {
|
||||
e.preventDefault();
|
||||
$(this).children('div.section-name-edit').show();
|
||||
$(this).children('span.section-name-span').hide();
|
||||
$(this).unbind('click', editSectionName);
|
||||
$(this).children('.section-name-edit').show();
|
||||
$(this).find('.edit-section-name').focus();
|
||||
$(this).children('.section-name-span').hide();
|
||||
$(this).find('.section-name-edit').bind('submit', saveEditSectionName);
|
||||
$(this).find('.edit-section-name-cancel').bind('click', cancelNewSection);
|
||||
$body.bind('keyup', { $cancelButton: $(this).find('.edit-section-name-cancel') }, checkForCancel);
|
||||
}
|
||||
|
||||
function cancelEditSectionName(e) {
|
||||
e.preventDefault();
|
||||
$(this).parent().hide();
|
||||
$(this).parent().siblings('span.section-name-span').show();
|
||||
$(this).parent().siblings('.section-name-span').show();
|
||||
$(this).closest('.section-name').bind('click', editSectionName);
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
function saveEditSectionName(e) {
|
||||
e.preventDefault();
|
||||
|
||||
id = $(this).closest("section.courseware-section").data("id");
|
||||
display_name = $.trim($(this).prev('.edit-section-name').val());
|
||||
$(this).closest('.section-name').unbind('click', editSectionName);
|
||||
|
||||
var id = $(this).closest('.courseware-section').data('id');
|
||||
var display_name = $.trim($(this).find('.edit-section-name').val());
|
||||
|
||||
$(this).closest('.courseware-section .section-name').append($spinner);
|
||||
$spinner.show();
|
||||
@@ -746,10 +772,10 @@ function saveEditSectionName(e) {
|
||||
}).success(function()
|
||||
{
|
||||
$spinner.delay(250).fadeOut(250);
|
||||
$_this.parent().siblings('span.section-name-span').html(display_name);
|
||||
$_this.parent().siblings('span.section-name-span').show();
|
||||
$_this.parent().hide();
|
||||
e.stopPropagation();
|
||||
$_this.closest('h3').find('.section-name-span').html(display_name).show();
|
||||
$_this.hide();
|
||||
$_this.closest('.section-name').bind('click', editSectionName);
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ CMS.Models.CourseInfo = Backbone.Model.extend({
|
||||
// course update -- biggest kludge here is the lack of a real id to map updates to originals
|
||||
CMS.Models.CourseUpdate = Backbone.Model.extend({
|
||||
defaults: {
|
||||
"date" : $.datepicker.formatDate('MM d', new Date()),
|
||||
"date" : $.datepicker.formatDate('MM d, yy', new Date()),
|
||||
"content" : ""
|
||||
}
|
||||
});
|
||||
@@ -29,6 +29,8 @@ CMS.Models.CourseUpdateCollection = Backbone.Collection.extend({
|
||||
|
||||
model : CMS.Models.CourseUpdate
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
10
cms/static/js/models/module_info.js
Normal file
10
cms/static/js/models/module_info.js
Normal file
@@ -0,0 +1,10 @@
|
||||
CMS.Models.ModuleInfo = Backbone.Model.extend({
|
||||
url: function() {return "/module_info/" + this.id;},
|
||||
|
||||
defaults: {
|
||||
"id": null,
|
||||
"data": null,
|
||||
"metadata" : null,
|
||||
"children" : null
|
||||
},
|
||||
});
|
||||
@@ -5,7 +5,7 @@
|
||||
if (typeof window.templateLoader == 'function') return;
|
||||
|
||||
var templateLoader = {
|
||||
templateVersion: "0.0.3",
|
||||
templateVersion: "0.0.8",
|
||||
templates: {},
|
||||
loadRemoteTemplate: function(templateName, filename, callback) {
|
||||
if (!this.templates[templateName]) {
|
||||
|
||||
@@ -13,7 +13,11 @@ CMS.Views.CourseInfoEdit = Backbone.View.extend({
|
||||
el: this.$('#course-update-view'),
|
||||
collection: this.model.get('updates')
|
||||
});
|
||||
// TODO instantiate the handouts view
|
||||
|
||||
new CMS.Views.ClassInfoHandoutsView({
|
||||
el: this.$('#course-handouts-view'),
|
||||
model: this.model.get('handouts')
|
||||
});
|
||||
return this;
|
||||
}
|
||||
});
|
||||
@@ -34,11 +38,11 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({
|
||||
// instantiates an editor template for each update in the collection
|
||||
window.templateLoader.loadRemoteTemplate("course_info_update",
|
||||
// TODO Where should the template reside? how to use the static.url to create the path?
|
||||
"/static/coffee/src/client_templates/course_info_update.html",
|
||||
function (raw_template) {
|
||||
"/static/client_templates/course_info_update.html",
|
||||
function (raw_template) {
|
||||
self.template = _.template(raw_template);
|
||||
self.render();
|
||||
}
|
||||
self.render();
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
@@ -53,28 +57,47 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({
|
||||
$(updateEle).append(newEle);
|
||||
});
|
||||
this.$el.find(".new-update-form").hide();
|
||||
this.$el.find('.date').datepicker({ 'dateFormat': 'MM d, yy' });
|
||||
return this;
|
||||
},
|
||||
|
||||
onNew: function(event) {
|
||||
var self = this;
|
||||
// create new obj, insert into collection, and render this one ele overriding the hidden attr
|
||||
var newModel = new CMS.Models.CourseUpdate();
|
||||
this.collection.add(newModel, {at : 0});
|
||||
|
||||
var newForm = this.template({ updateModel : newModel });
|
||||
var $newForm = $(this.template({ updateModel : newModel }));
|
||||
|
||||
var $textArea = $newForm.find(".new-update-content").first();
|
||||
if (this.$codeMirror == null ) {
|
||||
this.$codeMirror = CodeMirror.fromTextArea($textArea.get(0), {
|
||||
mode: "text/html",
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
});
|
||||
}
|
||||
|
||||
var updateEle = this.$el.find("#course-update-list");
|
||||
$(updateEle).append(newForm);
|
||||
$(newForm).find(".new-update-form").show();
|
||||
$(updateEle).prepend($newForm);
|
||||
$newForm.addClass('editing');
|
||||
this.$currentPost = $newForm.closest('li');
|
||||
|
||||
window.$modalCover.show();
|
||||
window.$modalCover.bind('click', function() {
|
||||
self.closeEditor(self, true);
|
||||
});
|
||||
|
||||
$('.date').datepicker('destroy');
|
||||
$('.date').datepicker({ 'dateFormat': 'MM d, yy' });
|
||||
},
|
||||
|
||||
onSave: function(event) {
|
||||
var targetModel = this.eventModel(event);
|
||||
targetModel.set({ date : this.dateEntry(event).val(), content : this.contentEntry(event).val() });
|
||||
// push change to display, hide the editor, submit the change
|
||||
$(this.dateDisplay(event)).val(targetModel.get('date'));
|
||||
$(this.contentDisplay(event)).val(targetModel.get('content'));
|
||||
$(this.editor(event)).hide();
|
||||
|
||||
console.log(this.contentEntry(event).val());
|
||||
targetModel.set({ date : this.dateEntry(event).val(), content : this.$codeMirror.getValue() });
|
||||
// push change to display, hide the editor, submit the change
|
||||
this.closeEditor(this);
|
||||
targetModel.save();
|
||||
},
|
||||
|
||||
@@ -82,14 +105,31 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({
|
||||
// change editor contents back to model values and hide the editor
|
||||
$(this.editor(event)).hide();
|
||||
var targetModel = this.eventModel(event);
|
||||
$(this.dateEntry(event)).val(targetModel.get('date'));
|
||||
$(this.contentEntry(event)).val(targetModel.get('content'));
|
||||
this.closeEditor(this, !targetModel.id);
|
||||
},
|
||||
|
||||
onEdit: function(event) {
|
||||
var self = this;
|
||||
this.$currentPost = $(event.target).closest('li');
|
||||
this.$currentPost.addClass('editing');
|
||||
|
||||
$(this.editor(event)).show();
|
||||
var $textArea = this.$currentPost.find(".new-update-content").first();
|
||||
if (this.$codeMirror == null ) {
|
||||
this.$codeMirror = CodeMirror.fromTextArea($textArea.get(0), {
|
||||
mode: "text/html",
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
});
|
||||
}
|
||||
|
||||
window.$modalCover.show();
|
||||
var targetModel = this.eventModel(event);
|
||||
window.$modalCover.bind('click', function() {
|
||||
self.closeEditor(self);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
onDelete: function(event) {
|
||||
// TODO ask for confirmation
|
||||
// remove the dom element and delete the model
|
||||
@@ -101,6 +141,24 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
closeEditor: function(self, removePost) {
|
||||
var targetModel = self.collection.getByCid(self.$currentPost.attr('name'));
|
||||
|
||||
if(removePost) {
|
||||
self.$currentPost.remove();
|
||||
}
|
||||
|
||||
// close the modal and insert the appropriate data
|
||||
self.$currentPost.removeClass('editing');
|
||||
self.$currentPost.find('.date-display').html(targetModel.get('date'));
|
||||
self.$currentPost.find('.date').val(targetModel.get('date'));
|
||||
self.$currentPost.find('.update-contents').html(targetModel.get('content'));
|
||||
self.$currentPost.find('.new-update-content').val(targetModel.get('content'));
|
||||
self.$currentPost.find('form').hide();
|
||||
window.$modalCover.unbind('click');
|
||||
window.$modalCover.hide();
|
||||
},
|
||||
|
||||
// Dereferencing from events to screen elements
|
||||
eventModel: function(event) {
|
||||
@@ -119,7 +177,7 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({
|
||||
|
||||
dateEntry: function(event) {
|
||||
var li = $(event.currentTarget).closest("li");
|
||||
if (li) return $(li).find("#date-entry").first();
|
||||
if (li) return $(li).find(".date").first();
|
||||
},
|
||||
|
||||
contentEntry: function(event) {
|
||||
@@ -135,4 +193,83 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
// the handouts view is dumb right now; it needs tied to a model and all that jazz
|
||||
CMS.Views.ClassInfoHandoutsView = Backbone.View.extend({
|
||||
// collection is CourseUpdateCollection
|
||||
events: {
|
||||
"click .save-button" : "onSave",
|
||||
"click .cancel-button" : "onCancel",
|
||||
"click .edit-button" : "onEdit"
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
var self = this;
|
||||
this.model.fetch(
|
||||
{
|
||||
complete: function() {
|
||||
window.templateLoader.loadRemoteTemplate("course_info_handouts",
|
||||
"/static/client_templates/course_info_handouts.html",
|
||||
function (raw_template) {
|
||||
self.template = _.template(raw_template);
|
||||
self.render();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var updateEle = this.$el;
|
||||
var self = this;
|
||||
this.$el.html(
|
||||
$(this.template( {
|
||||
model: this.model
|
||||
})
|
||||
)
|
||||
);
|
||||
this.$preview = this.$el.find('.handouts-content');
|
||||
this.$form = this.$el.find(".edit-handouts-form");
|
||||
this.$editor = this.$form.find('.handouts-content-editor');
|
||||
this.$form.hide();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
onEdit: function(event) {
|
||||
var self = this;
|
||||
this.$editor.val(this.$preview.html());
|
||||
this.$form.show();
|
||||
if (this.$codeMirror == null) {
|
||||
this.$codeMirror = CodeMirror.fromTextArea(this.$editor.get(0), {
|
||||
mode: "text/html",
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
});
|
||||
}
|
||||
window.$modalCover.show();
|
||||
window.$modalCover.bind('click', function() {
|
||||
self.closeEditor(self);
|
||||
});
|
||||
},
|
||||
|
||||
onSave: function(event) {
|
||||
this.model.set('data', this.$codeMirror.getValue());
|
||||
this.render();
|
||||
this.model.save();
|
||||
this.$form.hide();
|
||||
this.closeEditor(this);
|
||||
},
|
||||
|
||||
onCancel: function(event) {
|
||||
this.$form.hide();
|
||||
this.closeEditor(this);
|
||||
},
|
||||
|
||||
closeEditor: function(self) {
|
||||
this.$form.hide();
|
||||
window.$modalCover.unbind('click');
|
||||
window.$modalCover.hide();
|
||||
}
|
||||
});
|
||||
@@ -181,6 +181,11 @@ code {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.details {
|
||||
margin-bottom: 30px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
padding: 6px 14px;
|
||||
border-bottom: 1px solid #cbd1db;
|
||||
@@ -338,4 +343,29 @@ body.show-wip {
|
||||
content: '';
|
||||
@extend .spinner-icon;
|
||||
}
|
||||
}
|
||||
|
||||
.new-button {
|
||||
@include grey-button;
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
|
||||
&.big {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-button.standard,
|
||||
.delete-button.standard {
|
||||
float: left;
|
||||
@include white-button;
|
||||
padding: 3px 10px 4px;
|
||||
margin-left: 7px;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
|
||||
.edit-icon,
|
||||
.delete-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
@@ -51,14 +51,14 @@
|
||||
@include button;
|
||||
border: 1px solid $darkGrey;
|
||||
border-radius: 3px;
|
||||
@include linear-gradient(top, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0) 60%);
|
||||
@include linear-gradient(top, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0));
|
||||
background-color: #dfe5eb;
|
||||
@include box-shadow(0 1px 0 rgba(255, 255, 255, .3) inset);
|
||||
color: #5d6779;
|
||||
color: #778192;
|
||||
|
||||
&:hover {
|
||||
background-color: #f2f6f9;
|
||||
color: #5d6779;
|
||||
color: #778192;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,77 +1,179 @@
|
||||
body.updates {
|
||||
.course-info {
|
||||
h2 {
|
||||
margin-bottom: 24px;
|
||||
font-size: 22px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.course-info-wrapper {
|
||||
display: table;
|
||||
width: 100%;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.main-column,
|
||||
.course-handouts {
|
||||
float: none;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.main-column {
|
||||
border-radius: 3px 0 0 3px;
|
||||
border-right-color: $mediumGrey;
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
border: 1px solid #3c3c3c;
|
||||
background: #fff;
|
||||
color: #3c3c3c;
|
||||
}
|
||||
}
|
||||
|
||||
.course-updates {
|
||||
padding: 30px 40px;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
padding: 24px 0 32px;
|
||||
.update-list > li {
|
||||
padding: 34px 0 42px;
|
||||
border-top: 1px solid #cbd1db;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 18px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #646464;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
&.editing {
|
||||
position: relative;
|
||||
z-index: 1001;
|
||||
padding: 0;
|
||||
border-top: none;
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
|
||||
.post-preview {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
float: none;
|
||||
font-size: 24px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 18px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
line-height: 30px;
|
||||
color: #646464;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 34px 0 11px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.update-contents {
|
||||
padding-left: 30px;
|
||||
|
||||
p {
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-size: 16px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
p + p {
|
||||
margin-top: 18px;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.primary {
|
||||
border: 1px solid #ddd;
|
||||
background: #f6f6f6;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.new-update-button {
|
||||
@include grey-button;
|
||||
@include blue-button;
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 12px 0;
|
||||
padding: 18px 0;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.new-update-form {
|
||||
@include edit-box;
|
||||
margin-bottom: 24px;
|
||||
padding: 30px;
|
||||
border: none;
|
||||
|
||||
textarea {
|
||||
height: 180px;
|
||||
}
|
||||
}
|
||||
|
||||
.post-actions {
|
||||
float: right;
|
||||
|
||||
.edit-button,
|
||||
.delete-button{
|
||||
float: left;
|
||||
@include white-button;
|
||||
padding: 3px 10px 4px;
|
||||
margin-left: 7px;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
|
||||
.edit-icon,
|
||||
.delete-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.course-handouts {
|
||||
padding: 15px 20px;
|
||||
width: 30%;
|
||||
padding: 20px 30px;
|
||||
margin: 0;
|
||||
border-radius: 0 3px 3px 0;
|
||||
border-left: none;
|
||||
background: $lightGrey;
|
||||
|
||||
.new-handout-button {
|
||||
@include grey-button;
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 12px 0;
|
||||
margin-bottom: 28px;
|
||||
h2 {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 10px;
|
||||
.edit-button {
|
||||
float: right;
|
||||
@include white-button;
|
||||
padding: 3px 10px 4px;
|
||||
margin-left: 7px;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
|
||||
.edit-icon,
|
||||
.delete-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.handouts-content {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.new-handout-form {
|
||||
@include edit-box;
|
||||
margin-bottom: 24px;
|
||||
.treeview-handoutsnav li {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-handouts-form {
|
||||
@include edit-box;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
z-index: 10001;
|
||||
width: 800px;
|
||||
padding: 30px;
|
||||
|
||||
textarea {
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,7 @@ input.courseware-unit-search-input {
|
||||
}
|
||||
|
||||
.courseware-overview {
|
||||
.new-courseware-section-button {
|
||||
@include grey-button;
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.courseware-section {
|
||||
@@ -146,18 +141,18 @@ input.courseware-unit-search-input {
|
||||
|
||||
.section-name-edit {
|
||||
input {
|
||||
font-size: 16px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.save-button {
|
||||
@include blue-button;
|
||||
padding: 7px 20px 7px;
|
||||
padding: 10px 20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.cancel-button {
|
||||
@include white-button;
|
||||
padding: 7px 20px 7px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +200,7 @@ input.courseware-unit-search-input {
|
||||
.new-section-name-save,
|
||||
.new-subsection-name-save {
|
||||
@include blue-button;
|
||||
padding: 2px 20px 5px;
|
||||
padding: 6px 20px 8px;
|
||||
margin: 0 5px;
|
||||
color: #fff !important;
|
||||
}
|
||||
@@ -213,7 +208,7 @@ input.courseware-unit-search-input {
|
||||
.new-section-name-cancel,
|
||||
.new-subsection-name-cancel {
|
||||
@include white-button;
|
||||
padding: 2px 20px 5px;
|
||||
padding: 6px 20px 8px;
|
||||
color: #8891a1 !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
|
||||
.new-course-save {
|
||||
@include blue-button;
|
||||
// padding: ;
|
||||
}
|
||||
|
||||
.new-course-cancel {
|
||||
|
||||
@@ -137,6 +137,10 @@
|
||||
height: 11px;
|
||||
margin-right: 8px;
|
||||
background: url(../img/plus-icon.png) no-repeat;
|
||||
|
||||
&.white {
|
||||
background: url(../img/plus-icon-white.png) no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
.plus-icon-small {
|
||||
|
||||
69
cms/static/sass/_lms.scss
Normal file
69
cms/static/sass/_lms.scss
Normal file
@@ -0,0 +1,69 @@
|
||||
.component {
|
||||
font-family: 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
color: #3c3c3c;
|
||||
|
||||
a {
|
||||
color: #1d9dd9;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
h1 {
|
||||
float: none;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #646464;
|
||||
font-size: 19px;
|
||||
font-weight: 300;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 15px;
|
||||
margin-left: 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 19px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
h4 {
|
||||
background: none;
|
||||
padding: 0;
|
||||
border: none;
|
||||
@include box-shadow(none);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
code {
|
||||
margin: 0 2px;
|
||||
padding: 0px 5px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #eaeaea;
|
||||
white-space: nowrap;
|
||||
font-family: Monaco, monospace;
|
||||
font-size: 14px;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
p + h2, ul + h2, ol + h2, p + h3 {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
p + p, ul + p, ol + p {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #3c3c3c;
|
||||
font: normal 1em/1.6em;
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,72 @@
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
.unit-body {
|
||||
padding: 30px 40px;
|
||||
}
|
||||
|
||||
.components > li {
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
|
||||
&.new-component-item {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.component {
|
||||
border: 1px solid $mediumGrey;
|
||||
border-top: none;
|
||||
|
||||
&:first-child {
|
||||
border-top: 1px solid $mediumGrey;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border: 1px solid $mediumGrey;
|
||||
border-top: none;
|
||||
|
||||
&:first-child {
|
||||
border-top: 1px solid $mediumGrey;
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
background: url(../img/drag-handles.png) center no-repeat $lightGrey;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 11;
|
||||
width: 35px;
|
||||
border: none;
|
||||
background: url(../img/drag-handles.png) center no-repeat $lightGrey;
|
||||
|
||||
&:hover {
|
||||
background: url(../img/drag-handles.png) center no-repeat $lightGrey;
|
||||
}
|
||||
}
|
||||
|
||||
.component-actions {
|
||||
top: 26px;
|
||||
right: 44px;
|
||||
}
|
||||
}
|
||||
|
||||
.component.editing {
|
||||
.xmodule_display {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.xmodule_display {
|
||||
padding: 20px 20px 22px;
|
||||
font-size: 24px;
|
||||
font-weight: 300;
|
||||
background: $lightGrey;
|
||||
}
|
||||
|
||||
.static-page-item {
|
||||
position: relative;
|
||||
margin: 10px 0;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
}
|
||||
|
||||
.main-column {
|
||||
clear: both;
|
||||
float: left;
|
||||
width: 70%;
|
||||
}
|
||||
@@ -54,94 +55,11 @@
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
margin: 20px 40px;
|
||||
border: 1px solid #d1ddec;
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
@include transition(none);
|
||||
|
||||
&:hover {
|
||||
border-color: #6696d7;
|
||||
|
||||
.drag-handle,
|
||||
.component-actions a {
|
||||
background-color: $blue;
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
border-color: $blue;
|
||||
}
|
||||
}
|
||||
|
||||
&.editing {
|
||||
border-color: #6696d7;
|
||||
|
||||
.drag-handle,
|
||||
.component-actions {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.component-placeholder {
|
||||
border-color: #6696d7;
|
||||
}
|
||||
|
||||
.xmodule_display {
|
||||
padding: 40px 20px 20px;
|
||||
}
|
||||
|
||||
.component-actions {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
@include transition(opacity .15s);
|
||||
}
|
||||
|
||||
.edit-button,
|
||||
.delete-button {
|
||||
float: left;
|
||||
padding: 3px 10px 4px;
|
||||
margin-left: 3px;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
background: #d1ddec;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
@include transition(all .15s);
|
||||
|
||||
&:hover {
|
||||
background-color: $blue;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.edit-icon,
|
||||
.delete-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: -1px;
|
||||
right: -16px;
|
||||
z-index: -1;
|
||||
width: 15px;
|
||||
height: 100%;
|
||||
border-radius: 0 3px 3px 0;
|
||||
border: 1px solid #d1ddec;
|
||||
background: url(../img/white-drag-handles.png) center no-repeat #d1ddec;
|
||||
cursor: move;
|
||||
@include transition(all .15s);
|
||||
}
|
||||
|
||||
&.new-component-item {
|
||||
padding: 0;
|
||||
border: 1px solid #8891a1;
|
||||
border-radius: 3px;
|
||||
@include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0));
|
||||
background-color: #d1dae3;
|
||||
@include box-shadow(0 1px 0 rgba(255, 255, 255, .2) inset);
|
||||
@include transition(background-color .15s, border-color .15s);
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
|
||||
&.adding {
|
||||
background-color: $blue;
|
||||
@@ -223,8 +141,63 @@
|
||||
}
|
||||
}
|
||||
|
||||
.component {
|
||||
border: 1px solid #d1ddec;
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
@include transition(none);
|
||||
|
||||
&:hover {
|
||||
border-color: #6696d7;
|
||||
|
||||
.drag-handle {
|
||||
background-color: $blue;
|
||||
border-color: $blue;
|
||||
}
|
||||
}
|
||||
|
||||
&.editing {
|
||||
border-color: #6696d7;
|
||||
|
||||
.drag-handle,
|
||||
.component-actions {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.component-placeholder {
|
||||
border-color: #6696d7;
|
||||
}
|
||||
|
||||
.component-actions {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
right: 9px;
|
||||
@include transition(opacity .15s);
|
||||
|
||||
a {
|
||||
color: $darkGrey;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: -1px;
|
||||
right: -16px;
|
||||
z-index: -1;
|
||||
width: 15px;
|
||||
height: 100%;
|
||||
border-radius: 0 3px 3px 0;
|
||||
border: 1px solid #d1ddec;
|
||||
background: url(../img/white-drag-handles.png) center no-repeat #d1ddec;
|
||||
cursor: move;
|
||||
@include transition(all .15s);
|
||||
}
|
||||
}
|
||||
|
||||
.xmodule_display {
|
||||
padding: 10px 20px;
|
||||
padding: 40px 20px 20px;
|
||||
}
|
||||
|
||||
.component-editor {
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
.user-overview {
|
||||
@extend .window;
|
||||
padding: 30px 40px;
|
||||
|
||||
.details {
|
||||
margin-bottom: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.new-user-button {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
@import "modal";
|
||||
@import "alerts";
|
||||
@import "login";
|
||||
@import "lms";
|
||||
@import 'jquery-ui-calendar';
|
||||
|
||||
@import 'content-types';
|
||||
|
||||
Reference in New Issue
Block a user