New publishing controls on unit page (continued)
STUD-1707
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
"""
|
||||
Helper methods for Studio views.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponse
|
||||
@@ -13,11 +15,6 @@ from contentstore.utils import reverse_course_url, reverse_usage_url
|
||||
|
||||
__all__ = ['edge', 'event', 'landing']
|
||||
|
||||
EDITING_TEMPLATES = [
|
||||
"basic-modal", "modal-button", "edit-xblock-modal", "editor-mode-button", "upload-dialog", "image-modal",
|
||||
"add-xblock-component", "add-xblock-component-button", "add-xblock-component-menu",
|
||||
"add-xblock-component-menu-problem", "xblock-string-field-editor",
|
||||
]
|
||||
|
||||
# points to the temporary course landing page with log in and sign up
|
||||
def landing(request, org, course, coursename):
|
||||
|
||||
@@ -23,6 +23,8 @@ from contentstore.tests.utils import CourseTestCase
|
||||
from student.tests.factories import UserFactory
|
||||
from xmodule.capa_module import CapaDescriptor
|
||||
from xmodule.modulestore import PublishState
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.x_module import STUDIO_VIEW, STUDENT_VIEW
|
||||
from xblock.exceptions import NoSuchHandlerError
|
||||
from opaque_keys.edx.keys import UsageKey, CourseKey
|
||||
@@ -567,7 +569,7 @@ class TestEditItem(ItemTest):
|
||||
self.assertEqual(updated_draft.due, datetime(2077, 10, 10, 4, 0, tzinfo=UTC))
|
||||
self.assertIsNone(published.due)
|
||||
# Fetch the published version again to make sure the due date is still unset.
|
||||
published = modulestore().get_item(published.location, revision=REVISION_OPTION_PUBLISHED_ONLY)
|
||||
published = modulestore().get_item(published.location, revision=ModuleStoreEnum.RevisionOption.published_only)
|
||||
self.assertIsNone(published.due)
|
||||
|
||||
def test_make_public_with_update(self):
|
||||
@@ -620,7 +622,7 @@ class TestEditItem(ItemTest):
|
||||
draft = self.get_item_from_modulestore(self.problem_usage_key, verify_is_draft=True)
|
||||
self.assertNotEqual(draft.data, published.data)
|
||||
# Fetch the published version again to make sure the data is correct.
|
||||
published = modulestore().get_item(published.location, revision=REVISION_OPTION_PUBLISHED_ONLY)
|
||||
published = modulestore().get_item(published.location, revision=ModuleStoreEnum.RevisionOption.published_only)
|
||||
self.assertNotEqual(draft.data, published.data)
|
||||
|
||||
def test_publish_states_of_nested_xblocks(self):
|
||||
|
||||
@@ -44,8 +44,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
);
|
||||
};
|
||||
|
||||
respondWithJson = function(json) {
|
||||
var requestIndex = requests.length - 1;
|
||||
respondWithJson = function(json, requestIndex) {
|
||||
create_sinon.respondWithJson(
|
||||
requests,
|
||||
json,
|
||||
@@ -131,10 +130,29 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
draftBit = "draft",
|
||||
publishButtonCss = ".action-publish",
|
||||
discardChangesButtonCss = ".action-discard",
|
||||
request, lastRequest, promptSpies;
|
||||
request, lastRequest, promptSpies, sendDiscardChangesToServer;
|
||||
|
||||
lastRequest = function() { return requests[requests.length - 1]; };
|
||||
|
||||
sendDiscardChangesToServer = function(test) {
|
||||
// Helper function to do the discard operation, up until the server response.
|
||||
renderContainerPage(mockContainerXBlockHtml, test);
|
||||
fetch({"id": "locator-container", "published": true, "has_changes": true});
|
||||
expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled');
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(draftBit);
|
||||
// Click discard changes
|
||||
containerPage.$(discardChangesButtonCss).click();
|
||||
|
||||
// Confirm the discard.
|
||||
expect(promptSpies.constructor).toHaveBeenCalled();
|
||||
promptSpies.constructor.mostRecentCall.args[0].actions.primary.click(promptSpies);
|
||||
|
||||
request = lastRequest();
|
||||
expect(request.url).toEqual("/xblock/locator-container");
|
||||
expect(request.method).toEqual("DELETE");
|
||||
expect(request.requestBody).toEqual(null);
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
promptSpies = spyOnConstructor(Prompt, "Warning", ["show", "hide"]);
|
||||
promptSpies.show.andReturn(this.promptSpies);
|
||||
@@ -199,6 +217,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
// Verify updates displayed
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(publishedBit);
|
||||
// Verify that the "published" value has been cleared out of the model.
|
||||
expect(containerPage.model.get("publish")).toBeNull();
|
||||
});
|
||||
|
||||
it('can does not fetch if publish fails', function () {
|
||||
@@ -217,27 +237,26 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
// Verify still in draft state.
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(draftBit);
|
||||
// Verify that the "published" value has been cleared out of the model.
|
||||
expect(containerPage.model.get("publish")).toBeNull();
|
||||
});
|
||||
|
||||
/* STUD-1860
|
||||
it('can discard changes', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({"id": "locator-container", "published": true, "has_changes": true});
|
||||
expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled');
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(draftBit);
|
||||
// Click discard changes
|
||||
containerPage.$(discardChangesButtonCss).click();
|
||||
sendDiscardChangesToServer(this);
|
||||
|
||||
// Confirm the discard.
|
||||
expect(promptSpies.constructor).toHaveBeenCalled();
|
||||
promptSpies.constructor.mostRecentCall.args[0].actions.primary.click(promptSpies);
|
||||
var numRequests = requests.length;
|
||||
create_sinon.respondToDelete(requests);
|
||||
// Response to fetch, specifying the very next request (as multiple requests will be sent to server)
|
||||
respondWithJson({"id": "locator-container", "published": true, "has_changes": false}, numRequests);
|
||||
expect(containerPage.$(discardChangesButtonCss)).toHaveClass('is-disabled');
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(publishedBit);
|
||||
});
|
||||
*/
|
||||
|
||||
request = lastRequest();
|
||||
expect(request.url).toEqual("/xblock/locator-container");
|
||||
expect(request.method).toEqual("DELETE");
|
||||
expect(request.requestBody).toEqual(null);
|
||||
it('does not fetch if discard changes fails', function () {
|
||||
sendDiscardChangesToServer(this);
|
||||
|
||||
// Respond with failure because code does window.location.reload (which will
|
||||
// put tests into an infinite loop) on success.
|
||||
var numRequests = requests.length;
|
||||
// Respond with failure
|
||||
create_sinon.respondWithError(requests);
|
||||
@@ -249,8 +268,6 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
it('does not discard changes on cancel', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({"id": "locator-container", "published": true, "has_changes": true});
|
||||
expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled');
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(draftBit);
|
||||
var numRequests = requests.length;
|
||||
|
||||
// Click discard changes
|
||||
|
||||
@@ -28,7 +28,9 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/contai
|
||||
if (this.isUnitPage) {
|
||||
this.xblockPublisher = new ContainerSubviews.Publisher({
|
||||
el: this.$('#publish-unit'),
|
||||
model: this.model
|
||||
model: this.model,
|
||||
// When "Discard Changes" is clicked, the whole page must be re-rendered.
|
||||
renderPage: this.render
|
||||
});
|
||||
this.xblockPublisher.render();
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/feedba
|
||||
BaseView.prototype.initialize.call(this);
|
||||
this.template = this.loadTemplate('publish-xblock');
|
||||
this.model.on('sync', this.onSync, this);
|
||||
this.renderPage = this.options.renderPage;
|
||||
},
|
||||
|
||||
onSync: function(e) {
|
||||
@@ -121,6 +122,8 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/feedba
|
||||
this.runOperationShowingMessage(gettext('Publishing…'),
|
||||
function () {
|
||||
return xblockInfo.save({publish: 'make_public'});
|
||||
}).always(function() {
|
||||
xblockInfo.set("publish", null);
|
||||
}).done(function () {
|
||||
xblockInfo.fetch();
|
||||
});
|
||||
@@ -130,7 +133,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/feedba
|
||||
if (e && e.preventDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
var xblockInfo = this.model, view;
|
||||
var xblockInfo = this.model, view, renderPage = this.renderPage;
|
||||
|
||||
view = new PromptView.Warning({
|
||||
title: gettext("Discard Changes"),
|
||||
@@ -144,7 +147,19 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/feedba
|
||||
type: 'DELETE',
|
||||
url: xblockInfo.url()
|
||||
}).success(function () {
|
||||
return window.location.reload();
|
||||
window.alert("Refresh the page to see that changes were discarded. " +
|
||||
"Auto-refresh will be implemented in a later story.");
|
||||
/* Fetch is never returning on sandbox-- try
|
||||
doing a PUT instead of a DELETE with publish option
|
||||
to work around, or contact dev ops.
|
||||
STUD-1860
|
||||
window.crazyAjaxHandler = xblockInfo.fetch({
|
||||
complete: function(a, b, c) {
|
||||
debugger;
|
||||
}
|
||||
});
|
||||
renderPage();
|
||||
*/
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -11,7 +11,7 @@ else:
|
||||
import json
|
||||
|
||||
from xmodule.modulestore import PublishState
|
||||
from contentstore.views.helpers import xblock_studio_url, xblock_type_display_name, EDITING_TEMPLATES
|
||||
from contentstore.views.helpers import xblock_studio_url, xblock_type_display_name
|
||||
from django.utils.translation import ugettext as _
|
||||
%>
|
||||
<%block name="title">${xblock.display_name_with_default} ${xblock_type_display_name(xblock)}</%block>
|
||||
@@ -20,16 +20,17 @@ from django.utils.translation import ugettext as _
|
||||
<%namespace name='static' file='static_content.html'/>
|
||||
<%namespace name="units" file="widgets/units.html" />
|
||||
|
||||
|
||||
<%!
|
||||
templates = ["basic-modal", "modal-button", "edit-xblock-modal",
|
||||
"editor-mode-button", "upload-dialog", "image-modal",
|
||||
"add-xblock-component", "add-xblock-component-button", "add-xblock-component-menu",
|
||||
"add-xblock-component-menu-problem", "xblock-string-field-editor", "publish-xblock"]
|
||||
%>
|
||||
<%block name="header_extras">
|
||||
% for template_name in EDITING_TEMPLATES:
|
||||
% for template_name in templates:
|
||||
<script type="text/template" id="${template_name}-tpl">
|
||||
<%static:include path="js/${template_name}.underscore" />
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="publish-xblock-tpl">
|
||||
<%static:include path="js/publish-xblock.underscore" />
|
||||
</script>
|
||||
% endfor
|
||||
<link rel="stylesheet" type="text/css" href="${static.url('js/vendor/timepicker/jquery.timepicker.css')}" />
|
||||
</%block>
|
||||
@@ -40,7 +41,6 @@ from django.utils.translation import ugettext as _
|
||||
"js/collections/component_template", "xmodule", "coffee/src/main", "xblock/cms.runtime.v1"],
|
||||
function(doc, $, XBlockInfo, ContainerPage, ComponentTemplates, xmoduleLoader) {
|
||||
var templates = new ComponentTemplates(${component_templates | n}, {parse: true});
|
||||
// TODO: can go back to dumping on server side if easier.
|
||||
var mainXBlockInfo = new XBlockInfo(${json.dumps(xblock_info) | n});
|
||||
var isUnitPage = ${json.dumps(is_unit_page)}
|
||||
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
<% } %>
|
||||
</h3>
|
||||
|
||||
<!--To be added in STUDIO-1708-->
|
||||
<!--To be added in STUDIO-1826-->
|
||||
<!--<div class="wrapper-last-draft bar-mod-content">-->
|
||||
<!--<p class="copy meta">-->
|
||||
<!--Draft saved on 6/15/2014 at 12:45pm by amako-->
|
||||
<!--</p>-->
|
||||
<!--</div>-->
|
||||
|
||||
<!--To be added in STUD-1712-->
|
||||
<!--To be added in STUD-1829-->
|
||||
<!--<div class="wrapper-release bar-mod-content">-->
|
||||
<!--<h5 class="title">Will Release:</h5>-->
|
||||
<!--<p class="copy">-->
|
||||
@@ -23,7 +23,7 @@
|
||||
<!--</p>-->
|
||||
<!--</div>-->
|
||||
|
||||
<!--To be added in STUD-1713-->
|
||||
<!--To be added in STUD-1830-->
|
||||
<!--<div class="wrapper-visibility bar-mod-content">-->
|
||||
<!--<h5 class="title">Will be Visible to:</h5>-->
|
||||
<!--<p class="copy">Staff and Students</p>-->
|
||||
|
||||
Reference in New Issue
Block a user