Commit 4a45719a by Adam

Merge pull request #3560 from edx/adam/disable-links-ajax-2

Disable draft and edit links during ajax calls
parents 1b399581 7c13ba0c
define ["jquery", "jquery.ui", "gettext", "backbone",
"js/views/feedback_notification", "js/views/feedback_prompt",
"coffee/src/views/module_edit", "js/models/module_info"],
($, ui, gettext, Backbone, NotificationView, PromptView, ModuleEditView, ModuleModel) ->
class UnitEditView extends Backbone.View
"coffee/src/views/module_edit", "js/models/module_info",
"js/views/baseview"],
($, ui, gettext, Backbone, NotificationView, PromptView, ModuleEditView, ModuleModel, BaseView) ->
class UnitEditView extends BaseView
events:
'click .new-component .new-component-type a.multiple-templates': 'showComponentTemplates'
'click .new-component .new-component-type a.single-template': 'saveNewComponent'
......@@ -212,30 +213,35 @@ define ["jquery", "jquery.ui", "gettext", "backbone",
)
createDraft: (event) ->
@wait(true)
$.postJSON(@model.url(), {
publish: 'create_draft'
}, =>
analytics.track "Created Draft",
course: course_location_analytics
unit_id: unit_location_analytics
self = this
@disableElementWhileRunning($(event.target), ->
self.wait(true)
$.postJSON(self.model.url(), {
publish: 'create_draft'
}, =>
analytics.track "Created Draft",
course: course_location_analytics
unit_id: unit_location_analytics
@model.set('state', 'draft')
self.model.set('state', 'draft')
)
)
publishDraft: (event) ->
@wait(true)
@saveDraft()
$.postJSON(@model.url(), {
publish: 'make_public'
}, =>
analytics.track "Published Draft",
course: course_location_analytics
unit_id: unit_location_analytics
self = this
@disableElementWhileRunning($(event.target), ->
self.wait(true)
self.saveDraft()
$.postJSON(self.model.url(), {
publish: 'make_public'
}, =>
analytics.track "Published Draft",
course: course_location_analytics
unit_id: unit_location_analytics
@model.set('state', 'public')
self.model.set('state', 'public')
)
)
setVisibility: (event) ->
......@@ -259,7 +265,7 @@ define ["jquery", "jquery.ui", "gettext", "backbone",
@model.set('state', @$('.visibility-select').val())
)
class UnitEditView.NameEdit extends Backbone.View
class UnitEditView.NameEdit extends BaseView
events:
'change .unit-display-name-input': 'saveName'
......@@ -293,14 +299,14 @@ define ["jquery", "jquery.ui", "gettext", "backbone",
display_name: metadata.display_name
class UnitEditView.LocationState extends Backbone.View
class UnitEditView.LocationState extends BaseView
initialize: =>
@model.on('change:state', @render)
render: =>
@$el.toggleClass("#{@model.previous('state')}-item #{@model.get('state')}-item")
class UnitEditView.Visibility extends Backbone.View
class UnitEditView.Visibility extends BaseView
initialize: =>
@model.on('change:state', @render)
@render()
......
......@@ -76,5 +76,24 @@ define(["jquery", "underscore", "js/views/baseview", "js/utils/handle_iframe_bin
expect(view.$('.is-collapsible')).not.toHaveClass('collapsed');
});
});
describe("disabled element while running", function() {
it("adds 'is-disabled' class to element while action is running and removes it after", function() {
var viewWithLink,
link,
deferred = new $.Deferred(),
promise = deferred.promise(),
view = new BaseView();
setFixtures("<a href='#' id='link'>ripe apples drop about my head</a>");
link = $("#link");
expect(link).not.toHaveClass("is-disabled");
view.disableElementWhileRunning(link, function(){return promise});
expect(link).toHaveClass("is-disabled");
deferred.resolve();
expect(link).not.toHaveClass("is-disabled");
});
});
});
});
......@@ -162,5 +162,79 @@ define(["coffee/src/views/unit", "js/models/module_info", "js/spec_helpers/creat
verifyComponents(unit, ['loc_1', 'loc_2']);
});
});
describe("Disabled edit/publish links during ajax call", function() {
var unit,
link,
draft_states = [
{
state: "draft",
selector: ".publish-draft"
},
{
state: "public",
selector: ".create-draft"
}
],
editLinkFixture =
'<div class="main-wrapper edit-state-draft" data-locator="unit_locator"> \
<div class="unit-settings window"> \
<h4 class="header">Unit Settings</h4> \
<div class="window-contents"> \
<div class="row published-alert"> \
<p class="edit-draft-message"> \
<a href="#" class="create-draft">edit a draft</a> \
</p> \
<p class="publish-draft-message"> \
<a href="#" class="publish-draft">replace it with this draft</a> \
</p> \
</div> \
</div> \
</div> \
</div>';
function test_link_disabled_during_ajax_call(draft_state) {
beforeEach(function () {
setFixtures(editLinkFixture);
unit = new UnitEditView({
el: $('.main-wrapper'),
model: new ModuleModel({
id: 'unit_locator',
state: draft_state['state']
})
});
// needed to stub out the ajax
window.analytics = jasmine.createSpyObj('analytics', ['track']);
window.course_location_analytics = jasmine.createSpy('course_location_analytics');
window.unit_location_analytics = jasmine.createSpy('unit_location_analytics');
});
it("reenables the " + draft_state['selector'] + " link once the ajax call returns", function() {
runs(function(){
spyOn($, "ajax").andCallThrough();
spyOn($.fn, 'addClass').andCallThrough();
spyOn($.fn, 'removeClass').andCallThrough();
link = $(draft_state['selector']);
link.click();
});
waitsFor(function(){
// wait for "is-disabled" to be removed as a class
return !($(draft_state['selector']).hasClass("is-disabled"));
}, 500);
runs(function(){
// check that the `is-disabled` class was added and removed
expect($.fn.addClass).toHaveBeenCalledWith("is-disabled");
expect($.fn.removeClass).toHaveBeenCalledWith("is-disabled");
// make sure the link finishes without the `is-disabled` class
expect(link).not.toHaveClass("is-disabled");
// affirm that ajax was called
expect($.ajax).toHaveBeenCalled();
});
});
};
for (var i = 0; i < draft_states.length; i++) {
test_link_disabled_during_ajax_call(draft_states[i]);
};
});
}
);
define(["jquery", "underscore", "backbone", "js/utils/handle_iframe_binding"],
function ($, _, Backbone, IframeUtils) {
/*
This view is extended from backbone to provide useful functionality for all Studio views.
This functionality includes:
- automatic expand and collapse of elements with the 'ui-toggle-expansion' class specified
- additional control of rendering by overriding 'beforeRender' or 'afterRender'
This view is extended from backbone to provide useful functionality for all Studio views.
This functionality includes:
- automatic expand and collapse of elements with the 'ui-toggle-expansion' class specified
- additional control of rendering by overriding 'beforeRender' or 'afterRender'
Note: the default 'afterRender' function calls a utility function 'iframeBinding' which modifies
iframe src urls on a page so that they are rendered as part of the DOM.
Note: the default 'afterRender' function calls a utility function 'iframeBinding' which modifies
iframe src urls on a page so that they are rendered as part of the DOM.
*/
var BaseView = Backbone.View.extend({
......@@ -61,6 +61,20 @@ define(["jquery", "underscore", "backbone", "js/utils/handle_iframe_binding"],
},
/**
* Disables a given element when a given operation is running.
* @param {jQuery} element: the element to be disabled.
* @param operation: the operation during whose duration the
* element should be disabled. The operation should return
* a jquery promise.
*/
disableElementWhileRunning: function(element, operation) {
element.addClass("is-disabled");
operation().always(function() {
element.removeClass("is-disabled");
});
},
/**
* Loads the named template from the page, or logs an error if it fails.
* @param name The name of the template.
* @returns The loaded template.
......
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