Commit 44251612 by Calen Pennington

Merge pull request #936 from MITx/feature/cas/tomg/saving-conventions

new saving conventions
parents 35d50976 fb2925a2
...@@ -57,7 +57,7 @@ class CMS.Views.ModuleEdit extends Backbone.View ...@@ -57,7 +57,7 @@ class CMS.Views.ModuleEdit extends Backbone.View
data = @module.save() data = @module.save()
data.metadata = @metadata() data.metadata = @metadata()
@model.save(data).done( => @model.save(data).done( =>
showToastMessage("Your changes have been saved.", null, 3) # # showToastMessage("Your changes have been saved.", null, 3)
@module = null @module = null
@render() @render()
@$el.removeClass('editing') @$el.removeClass('editing')
......
...@@ -177,6 +177,7 @@ class CMS.Views.UnitEdit.NameEdit extends Backbone.View ...@@ -177,6 +177,7 @@ class CMS.Views.UnitEdit.NameEdit extends Backbone.View
initialize: => initialize: =>
@model.on('change:metadata', @render) @model.on('change:metadata', @render)
@saveName @saveName
@$spinner = $('<span class="spinner-in-field-icon"></span>');
render: => render: =>
@$('.unit-display-name-input').val(@model.get('metadata').display_name) @$('.unit-display-name-input').val(@model.get('metadata').display_name)
...@@ -186,7 +187,27 @@ class CMS.Views.UnitEdit.NameEdit extends Backbone.View ...@@ -186,7 +187,27 @@ class CMS.Views.UnitEdit.NameEdit extends Backbone.View
metadata = $.extend({}, @model.get('metadata')) metadata = $.extend({}, @model.get('metadata'))
metadata.display_name = @$('.unit-display-name-input').val() metadata.display_name = @$('.unit-display-name-input').val()
$('.unit-location .editing .unit-name').html(metadata.display_name) $('.unit-location .editing .unit-name').html(metadata.display_name)
@model.set('metadata', metadata) @model.set 'metadata', metadata
inputField = this.$el.find('input')
# add a spinner
@$spinner.css({
'position': 'absolute',
'top': Math.floor(inputField.position().top + (inputField.outerHeight() / 2) + 3),
'left': inputField.position().left + inputField.outerWidth() - 24,
'margin-top': '-10px'
});
inputField.after(@$spinner);
# save the name after a slight delay
if @timer
clearTimeout @timer
@timer = setTimeout( =>
@model.save()
@timer = null
@$spinner.delay(500).fadeOut(150)
, 500)
class CMS.Views.UnitEdit.LocationState extends Backbone.View class CMS.Views.UnitEdit.LocationState extends Backbone.View
initialize: => initialize: =>
......
...@@ -4,6 +4,8 @@ var $modalCover; ...@@ -4,6 +4,8 @@ var $modalCover;
var $newComponentItem; var $newComponentItem;
var $newComponentStep1; var $newComponentStep1;
var $newComponentStep2; var $newComponentStep2;
var $changedInput;
var $spinner;
$(document).ready(function() { $(document).ready(function() {
$body = $('body'); $body = $('body');
...@@ -13,6 +15,7 @@ $(document).ready(function() { ...@@ -13,6 +15,7 @@ $(document).ready(function() {
$newComponentTypePicker = $('.new-component'); $newComponentTypePicker = $('.new-component');
$newComponentTemplatePickers = $('.new-component-templates'); $newComponentTemplatePickers = $('.new-component-templates');
$newComponentButton = $('.new-component-button'); $newComponentButton = $('.new-component-button');
$spinner = $('<span class="spinner-in-field-icon"></span>');
$body.bind('keyup', onKeyUp); $body.bind('keyup', onKeyUp);
$('.expand-collapse-icon').bind('click', toggleSubmodules); $('.expand-collapse-icon').bind('click', toggleSubmodules);
...@@ -31,6 +34,14 @@ $(document).ready(function() { ...@@ -31,6 +34,14 @@ $(document).ready(function() {
$('.new-unit-item').bind('click', createNewUnit); $('.new-unit-item').bind('click', createNewUnit);
$('.save-subsection').bind('click', saveSubsection); $('.save-subsection').bind('click', saveSubsection);
// autosave when a field is updated on the subsection page
$body.on('keyup', '.subsection-display-name-input, .unit-subtitle, .policy-list-value', checkForNewValue);
$('.subsection-display-name-input, .unit-subtitle, .policy-list-name, .policy-list-value').each(function(i) {
this.val = $(this).val();
});
$("#start_date, #start_time, #due_date, #due_time").bind('change', autosaveInput);
$('.sync-date, .remove-date').bind('click', autosaveInput);
// making the unit list sortable // making the unit list sortable
$('.sortable-unit-list').sortable({ $('.sortable-unit-list').sortable({
axis: 'y', axis: 'y',
...@@ -62,7 +73,7 @@ $(document).ready(function() { ...@@ -62,7 +73,7 @@ $(document).ready(function() {
}); });
// Subsection reordering // Subsection reordering
$('.unit-list ol').sortable({ $('.subsection-list > ol').sortable({
axis: 'y', axis: 'y',
handle: '.section-item .drag-handle', handle: '.section-item .drag-handle',
update: onSubsectionReordered update: onSubsectionReordered
...@@ -101,7 +112,7 @@ function showImportSubmit(e) { ...@@ -101,7 +112,7 @@ function showImportSubmit(e) {
$('.file-name-block').show(); $('.file-name-block').show();
$('.import .choose-file-button').hide(); $('.import .choose-file-button').hide();
$('.submit-button').show(); $('.submit-button').show();
$('.progress').show(); $('.progress').show();
} else { } else {
$('.error-block').html('File format not supported. Please upload a file with a <code>tar.gz</code> extension.').show(); $('.error-block').html('File format not supported. Please upload a file with a <code>tar.gz</code> extension.').show();
} }
...@@ -109,27 +120,48 @@ function showImportSubmit(e) { ...@@ -109,27 +120,48 @@ function showImportSubmit(e) {
function syncReleaseDate(e) { function syncReleaseDate(e) {
e.preventDefault(); e.preventDefault();
$(this).closest('.notice').hide();
$("#start_date").val(""); $("#start_date").val("");
$("#start_time").val(""); $("#start_time").val("");
} }
function addPolicyMetadata(e) { function addPolicyMetadata(e) {
e.preventDefault(); e.preventDefault();
var template =$('#add-new-policy-element-template > li'); var template =$('#add-new-policy-element-template > li');
var newNode = template.clone(); var newNode = template.clone();
var _parent_el = $(this).parent('ol:.policy-list'); var _parent_el = $(this).parent('ol:.policy-list');
newNode.insertBefore('.add-policy-data'); newNode.insertBefore('.add-policy-data');
$('.remove-policy-data').bind('click', removePolicyMetadata); $('.remove-policy-data').bind('click', removePolicyMetadata);
newNode.find('.policy-list-name').focus();
newNode.find('.save-button').bind('click', savePolicyMetadata);
newNode.find('.cancel-button').bind('click', cancelPolicyMetadata);
}
function savePolicyMetadata(e) {
e.preventDefault();
$('.save-subsection').click();
$(this).parents('.policy-list-element').removeClass('new-policy-list-element');
}
function cancelPolicyMetadata(e) {
e.preventDefault();
$(this).parents('.policy-list-element').remove();
} }
function removePolicyMetadata(e) { function removePolicyMetadata(e) {
e.preventDefault(); e.preventDefault();
if(!confirm('Are you sure you wish to delete this item. It cannot be reversed!'))
return;
policy_name = $(this).data('policy-name'); policy_name = $(this).data('policy-name');
var _parent_el = $(this).parent('li:.policy-list-element'); var _parent_el = $(this).parent('li:.policy-list-element');
if ($(_parent_el).hasClass("new-policy-list-element")) if ($(_parent_el).hasClass("new-policy-list-element")) {
_parent_el.remove(); _parent_el.remove();
else } else {
_parent_el.appendTo("#policy-to-delete"); _parent_el.appendTo("#policy-to-delete");
}
$('.save-subsection').click();
} }
...@@ -207,8 +239,55 @@ function getEdxTimeFromDateTimeInputs(date_id, time_id, format) { ...@@ -207,8 +239,55 @@ function getEdxTimeFromDateTimeInputs(date_id, time_id, format) {
return getEdxTimeFromDateTimeVals(input_date, input_time, format); return getEdxTimeFromDateTimeVals(input_date, input_time, format);
} }
function checkForNewValue(e) {
if($(this).parents('.new-policy-list-element')[0]) {
return;
}
if(this.val) {
this.hasChanged = this.val != $(this).val();
} else {
this.hasChanged = false;
}
this.val = $(this).val();
if(this.hasChanged) {
if(this.saveTimer) {
clearTimeout(this.saveTimer);
}
this.saveTimer = setTimeout(function() {
$changedInput = $(e.target);
$('.save-subsection').click();
this.saveTimer = null;
}, 500);
}
}
function autosaveInput(e) {
if(this.saveTimer) {
clearTimeout(this.saveTimer);
}
this.saveTimer = setTimeout(function() {
$changedInput = $(e.target);
$('.save-subsection').click();
this.saveTimer = null;
}, 500);
}
function saveSubsection(e) { function saveSubsection(e) {
e.preventDefault(); e.preventDefault();
if($changedInput && !$changedInput.hasClass('no-spinner')) {
$spinner.css({
'position': 'absolute',
'top': Math.floor($changedInput.position().top + ($changedInput.outerHeight() / 2) + 3),
'left': $changedInput.position().left + $changedInput.outerWidth() - 24,
'margin-top': '-10px'
});
$changedInput.after($spinner);
}
var id = $(this).data('id'); var id = $(this).data('id');
...@@ -252,10 +331,10 @@ function saveSubsection(e) { ...@@ -252,10 +331,10 @@ function saveSubsection(e) {
contentType: "application/json", contentType: "application/json",
data:JSON.stringify({ 'id' : id, 'metadata' : metadata, 'data': null, 'children' : children}), data:JSON.stringify({ 'id' : id, 'metadata' : metadata, 'data': null, 'children' : children}),
success: function() { success: function() {
alert('Your changes have been saved.'); $spinner.delay(500).fadeOut(150);
}, },
error: function() { error: function() {
alert('There has been an error while saving your changes.'); showToastMessage('There has been an error while saving your changes.');
} }
}); });
} }
...@@ -550,7 +629,7 @@ function addNewSubsection(e) { ...@@ -550,7 +629,7 @@ function addNewSubsection(e) {
e.preventDefault(); e.preventDefault();
var $section = $(this).closest('.courseware-section'); var $section = $(this).closest('.courseware-section');
var $newSubsection = $($('#new-subsection-template').html()); var $newSubsection = $($('#new-subsection-template').html());
$section.find('.unit-list > ol').append($newSubsection); $section.find('.subsection-list > ol').append($newSubsection);
$section.find('.new-subsection-name-input').focus().select(); $section.find('.new-subsection-name-input').focus().select();
var $saveButton = $newSubsection.find('.new-subsection-name-save'); var $saveButton = $newSubsection.find('.new-subsection-name-save');
...@@ -561,7 +640,7 @@ function addNewSubsection(e) { ...@@ -561,7 +640,7 @@ function addNewSubsection(e) {
$saveButton.data('parent', parent) $saveButton.data('parent', parent)
$saveButton.data('template', $(this).data('template')); $saveButton.data('template', $(this).data('template'));
$newSubsection.find('.new-subsection-name-cancel').bind('click', cancelNewSubsection); $newSubsection.find('.new-subsection-name-cancel').bind('click', cancelNewSubsection);
} }
function saveNewSubsection(e) { function saveNewSubsection(e) {
...@@ -583,8 +662,6 @@ function saveNewSubsection(e) { ...@@ -583,8 +662,6 @@ function saveNewSubsection(e) {
location.reload(); location.reload();
} }
}); });
} }
function cancelNewSubsection(e) { function cancelNewSubsection(e) {
......
...@@ -38,8 +38,8 @@ input.courseware-unit-search-input { ...@@ -38,8 +38,8 @@ input.courseware-unit-search-input {
} }
} }
&.collapsed .unit-list, &.collapsed .subsection-list,
.collapsed .unit-list, .collapsed .subsection-list,
.collapsed > ol { .collapsed > ol {
display: none !important; display: none !important;
} }
...@@ -94,7 +94,7 @@ input.courseware-unit-search-input { ...@@ -94,7 +94,7 @@ input.courseware-unit-search-input {
border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0;
} }
.unit-list { .subsection-list {
margin: 0 12px; margin: 0 12px;
> ol { > ol {
......
...@@ -269,3 +269,11 @@ ...@@ -269,3 +269,11 @@
vertical-align: middle; vertical-align: middle;
background: url(../img/blue-spinner.gif) no-repeat; background: url(../img/blue-spinner.gif) no-repeat;
} }
.spinner-in-field-icon {
display: inline-block;
width: 14px;
height: 14px;
vertical-align: middle;
background: url(../img/spinner-in-field.gif) no-repeat;
}
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
width: 100%; width: 100%;
} }
.unit-list { .sortable-unit-list {
ol { ol {
@include tree-view; @include tree-view;
} }
...@@ -24,15 +24,39 @@ ...@@ -24,15 +24,39 @@
.policy-list { .policy-list {
.policy-list-name { .policy-list-name {
margin-right: 5px; margin-right: 5px;
margin-bottom: 10px;
} }
.policy-list-value { .policy-list-value {
margin-right: 10px; margin-right: 10px;
} }
}
.policy-list-element {
.save-button,
.cancel-button {
display: none;
}
}
li { .new-policy-list-element {
padding: 10px 10px 0;
margin: 0 -10px;
border-radius: 3px;
background: $mediumGrey;
.save-button {
@include blue-button;
margin-bottom: 10px; margin-bottom: 10px;
} }
.cancel-button {
@include white-button;
}
.delete-icon {
display: none;
}
} }
.new-policy-item { .new-policy-item {
......
...@@ -276,7 +276,7 @@ ...@@ -276,7 +276,7 @@
} }
} }
.unit-properties { .unit-settings {
.window-contents { .window-contents {
padding: 10px 20px; padding: 10px 20px;
} }
...@@ -323,6 +323,7 @@ ...@@ -323,6 +323,7 @@
.save-button { .save-button {
@include blue-button; @include blue-button;
display: none;
} }
.save-button, .save-button,
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
</article> </article>
</div> </div>
<div class="sidebar"> <div class="sidebar">
<div class="unit-properties window"> <div class="unit-settings window">
<h4>Page Settings</h4> <h4>Page Settings</h4>
<div class="window-contents"> <div class="window-contents">
<div class="row visibility"> <div class="row visibility">
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
<label>Format:</label> <label>Format:</label>
<input type="text" value="${subsection.metadata['format'] if 'format' in subsection.metadata else ''}" class="unit-subtitle" data-metadata-name="format"/> <input type="text" value="${subsection.metadata['format'] if 'format' in subsection.metadata else ''}" class="unit-subtitle" data-metadata-name="format"/>
</div> </div>
<div class="unit-list"> <div class="sortable-unit-list">
<label>Units:</label> <label>Units:</label>
${units.enum_units(subsection, subsection_units=subsection_units)} ${units.enum_units(subsection, subsection_units=subsection_units)}
</div> </div>
...@@ -51,11 +51,16 @@ ...@@ -51,11 +51,16 @@
</div> </div>
<div id="add-new-policy-element-template" style="display:none"> <div id="add-new-policy-element-template" style="display:none">
<li class="policy-list-element new-policy-list-element"><input type="text" class="policy-list-name" autocomplete="off" size="15"/>:&nbsp;<input type="text" class="policy-list-value" size=40 autocomplete="off"/><a href="#" class="delete-icon remove-policy-data"></a></li> <li class="policy-list-element new-policy-list-element">
<input type="text" class="policy-list-name" autocomplete="off" size="15"/>:&nbsp;<input type="text" class="policy-list-value" size=40 autocomplete="off"/>
<a href="#" class="save-button">Save</a>
<a href="#" class="cancel-button">Cancel</a>
<a href="#" class="delete-icon remove-policy-data"></a>
</li>
</div> </div>
<div class="sidebar"> <div class="sidebar">
<div class="unit-properties window"> <div class="unit-settings window">
<h4>Subsection Settings</h4> <h4>Subsection Settings</h4>
<div class="window-contents"> <div class="window-contents">
<div class="scheduled-date-input row"> <div class="scheduled-date-input row">
...@@ -74,7 +79,7 @@ ...@@ -74,7 +79,7 @@
% else: % else:
<p class="notice">The date above differs from the release date of ${parent_item.display_name} – ${parent_start_date.strftime('%m/%d/%Y')} at ${parent_start_date.strftime('%H:%M')}. <p class="notice">The date above differs from the release date of ${parent_item.display_name} – ${parent_start_date.strftime('%m/%d/%Y')} at ${parent_start_date.strftime('%H:%M')}.
% endif % endif
<a href="#" class="sync-date">Sync to ${parent_item.display_name}.</a></p> <a href="#" class="sync-date no-spinner">Sync to ${parent_item.display_name}.</a></p>
% endif % endif
</div> </div>
<div class="due-date-input row"> <div class="due-date-input row">
......
...@@ -98,7 +98,7 @@ ...@@ -98,7 +98,7 @@
<a href="#" class="drag-handle"></a> <a href="#" class="drag-handle"></a>
</div> </div>
</header> </header>
<div class="unit-list"> <div class="subsection-list">
<div class="list-header"> <div class="list-header">
<a href="#" class="new-subsection-item" data-template="${new_subsection_template}"> <a href="#" class="new-subsection-item" data-template="${new_subsection_template}">
<span class="new-folder-icon"></span>New Subsection <span class="new-folder-icon"></span>New Subsection
......
...@@ -70,8 +70,8 @@ ...@@ -70,8 +70,8 @@
</div> </div>
<div class="sidebar"> <div class="sidebar">
<div class="unit-properties window"> <div class="unit-settings window">
<h4>Unit Properties</h4> <h4>Unit Settings</h4>
<div class="window-contents"> <div class="window-contents">
<div class="row visibility"> <div class="row visibility">
<label class="inline-label">Visibility:</label> <label class="inline-label">Visibility:</label>
......
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