Support staff locking on the unit page
STUD-1873
This commit is contained in:
@@ -38,7 +38,7 @@ define(["backbone", "underscore", "js/utils/module"], function(Backbone, _, Modu
|
||||
* If true, only course staff can see the xblock regardless of publish status or
|
||||
* release date status.
|
||||
*/
|
||||
"locked": null,
|
||||
"visible_to_staff_only": null,
|
||||
/**
|
||||
* Date of the last edit to this xblock or any of its descendants.
|
||||
*/
|
||||
@@ -69,7 +69,12 @@ define(["backbone", "underscore", "js/utils/module"], function(Backbone, _, Modu
|
||||
* this will either be the parent subsection or the grandparent section.
|
||||
* This can be null if the release date is unscheduled.
|
||||
*/
|
||||
"release_date_from":null
|
||||
"release_date_from":null,
|
||||
/**
|
||||
* True if this xblock is currently visible to students. This is computed server-side
|
||||
* so that the logic isn't duplicated on the client.
|
||||
*/
|
||||
"currently_visible_to_students": null
|
||||
},
|
||||
|
||||
parse: function(response) {
|
||||
|
||||
@@ -48,7 +48,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
);
|
||||
};
|
||||
|
||||
renderContainerPage = function(html, test, options) {
|
||||
renderContainerPage = function(test, html, options) {
|
||||
requests = create_sinon.requests(test);
|
||||
containerPage = new ContainerPage(_.extend(options || {}, {
|
||||
model: model,
|
||||
@@ -70,7 +70,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
describe("Initial display", function() {
|
||||
it('can render itself', function() {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
expect(containerPage.$('.xblock-header').length).toBe(9);
|
||||
expect(containerPage.$('.wrapper-xblock .level-nesting')).not.toHaveClass('is-hidden');
|
||||
});
|
||||
@@ -84,7 +84,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
});
|
||||
|
||||
it('inline edits the display name when performing a new action', function() {
|
||||
renderContainerPage(mockContainerXBlockHtml, this, {
|
||||
renderContainerPage(this, mockContainerXBlockHtml, {
|
||||
action: 'new'
|
||||
});
|
||||
expect(containerPage.$('.xblock-header').length).toBe(9);
|
||||
@@ -106,8 +106,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
};
|
||||
|
||||
expectEditCanceled = function(test, options) {
|
||||
var initialRequests, displayNameWrapper;
|
||||
renderContainerPage(mockContainerXBlockHtml, test);
|
||||
var initialRequests, displayNameWrapper, displayNameInput;
|
||||
renderContainerPage(test, mockContainerXBlockHtml);
|
||||
displayNameWrapper = getDisplayNameWrapper();
|
||||
initialRequests = requests.length;
|
||||
displayNameInput = edit_helpers.inlineEdit(displayNameWrapper, options.newTitle);
|
||||
@@ -125,7 +125,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('can edit itself', function() {
|
||||
var editButtons, displayNameElement;
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
displayNameElement = containerPage.$('.page-header-title');
|
||||
|
||||
// Click the root edit button
|
||||
@@ -162,7 +162,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('can inline edit the display name', function() {
|
||||
var displayNameInput, displayNameWrapper;
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
displayNameWrapper = getDisplayNameWrapper();
|
||||
displayNameInput = edit_helpers.inlineEdit(displayNameWrapper, updatedDisplayName);
|
||||
displayNameInput.change();
|
||||
@@ -176,7 +176,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('does not change the title when a display name update fails', function() {
|
||||
var initialRequests, displayNameInput, displayNameWrapper;
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
displayNameWrapper = getDisplayNameWrapper();
|
||||
displayNameInput = edit_helpers.inlineEdit(displayNameWrapper, updatedDisplayName);
|
||||
initialRequests = requests.length;
|
||||
@@ -190,7 +190,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('trims whitespace from the display name', function() {
|
||||
var displayNameInput, displayNameWrapper;
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
displayNameWrapper = getDisplayNameWrapper();
|
||||
displayNameInput = edit_helpers.inlineEdit(displayNameWrapper, updatedDisplayName + ' ');
|
||||
displayNameInput.change();
|
||||
@@ -222,7 +222,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('can show an edit modal for a child xblock', function() {
|
||||
var editButtons;
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
editButtons = containerPage.$('.wrapper-xblock .edit-button');
|
||||
// The container should have rendered six mock xblocks
|
||||
expect(editButtons.length).toBe(6);
|
||||
@@ -258,7 +258,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
it('can save changes to settings', function() {
|
||||
var editButtons, modal, mockUpdatedXBlockHtml;
|
||||
mockUpdatedXBlockHtml = readFixtures('mock/mock-updated-xblock.underscore');
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
editButtons = containerPage.$('.wrapper-xblock .edit-button');
|
||||
// The container should have rendered six mock xblocks
|
||||
expect(editButtons.length).toBe(6);
|
||||
@@ -346,24 +346,24 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
};
|
||||
|
||||
it("can delete the first xblock", function() {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
deleteComponentWithSuccess(0);
|
||||
});
|
||||
|
||||
it("can delete a middle xblock", function() {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
deleteComponentWithSuccess(1);
|
||||
});
|
||||
|
||||
it("can delete the last xblock", function() {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
deleteComponentWithSuccess(NUM_COMPONENTS_PER_GROUP - 1);
|
||||
});
|
||||
|
||||
it('does not delete when clicking No in prompt', function () {
|
||||
var numRequests;
|
||||
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
numRequests = requests.length;
|
||||
|
||||
// click delete on the first component but press no
|
||||
@@ -378,7 +378,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('shows a notification during the delete operation', function() {
|
||||
var notificationSpy = edit_helpers.createNotificationSpy();
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
clickDelete(0);
|
||||
edit_helpers.verifyNotificationShowing(notificationSpy, /Deleting/);
|
||||
create_sinon.respondWithJson(requests, {});
|
||||
@@ -387,7 +387,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('does not delete an xblock upon failure', function () {
|
||||
var notificationSpy = edit_helpers.createNotificationSpy();
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
clickDelete(0);
|
||||
edit_helpers.verifyNotificationShowing(notificationSpy, /Deleting/);
|
||||
create_sinon.respondWithError(requests);
|
||||
@@ -431,23 +431,23 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
};
|
||||
|
||||
it("can duplicate the first xblock", function() {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
duplicateComponentWithSuccess(0);
|
||||
});
|
||||
|
||||
it("can duplicate a middle xblock", function() {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
duplicateComponentWithSuccess(1);
|
||||
});
|
||||
|
||||
it("can duplicate the last xblock", function() {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
duplicateComponentWithSuccess(NUM_COMPONENTS_PER_GROUP - 1);
|
||||
});
|
||||
|
||||
it('shows a notification when duplicating', function () {
|
||||
var notificationSpy = edit_helpers.createNotificationSpy();
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
clickDuplicate(0);
|
||||
edit_helpers.verifyNotificationShowing(notificationSpy, /Duplicating/);
|
||||
create_sinon.respondWithJson(requests, {"locator": "new_item"});
|
||||
@@ -456,7 +456,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('does not duplicate an xblock upon failure', function () {
|
||||
var notificationSpy = edit_helpers.createNotificationSpy();
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
refreshXBlockSpies = spyOn(containerPage, "refreshXBlock");
|
||||
clickDuplicate(0);
|
||||
edit_helpers.verifyNotificationShowing(notificationSpy, /Duplicating/);
|
||||
@@ -475,7 +475,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
};
|
||||
|
||||
it('sends the correct JSON to the server', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
clickNewComponent(0);
|
||||
edit_helpers.verifyXBlockRequest(requests, {
|
||||
"category": "discussion",
|
||||
@@ -486,7 +486,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('shows a notification while creating', function () {
|
||||
var notificationSpy = edit_helpers.createNotificationSpy();
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
clickNewComponent(0);
|
||||
edit_helpers.verifyNotificationShowing(notificationSpy, /Adding/);
|
||||
create_sinon.respondWithJson(requests, { });
|
||||
@@ -495,7 +495,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('does not insert component upon failure', function () {
|
||||
var requestCount;
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
clickNewComponent(0);
|
||||
requestCount = requests.length;
|
||||
create_sinon.respondWithError(requests);
|
||||
@@ -514,7 +514,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
verifyCreateHtmlComponent = function(test, templateIndex, expectedRequest) {
|
||||
var xblockCount;
|
||||
renderContainerPage(mockContainerXBlockHtml, test);
|
||||
renderContainerPage(test, mockContainerXBlockHtml);
|
||||
showTemplatePicker();
|
||||
xblockCount = containerPage.$('.studio-xblock-wrapper').length;
|
||||
containerPage.$('.new-component-html a')[templateIndex].click();
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers",
|
||||
"js/views/feedback_prompt", "js/views/pages/container", "js/views/pages/container_subviews",
|
||||
"js/models/xblock_info"],
|
||||
"js/views/feedback_prompt", "js/views/pages/container", "js/views/pages/container_subviews",
|
||||
"js/models/xblock_info"],
|
||||
function ($, _, str, create_sinon, edit_helpers, Prompt, ContainerPage, ContainerSubviews, XBlockInfo) {
|
||||
|
||||
describe("Container Subviews", function() {
|
||||
var model, containerPage, requests, renderContainerPage, respondWithHtml, respondWithJson, fetch,
|
||||
disabledCss = "is-disabled",
|
||||
var model, containerPage, requests, createContainerPage, renderContainerPage,
|
||||
respondWithHtml, respondWithJson, fetch,
|
||||
disabledCss = "is-disabled", defaultXBlockInfo, createXBlockInfo,
|
||||
mockContainerPage = readFixtures('mock/mock-container-page.underscore'),
|
||||
mockContainerXBlockHtml = readFixtures('mock/mock-empty-container-xblock.underscore');
|
||||
|
||||
@@ -14,27 +15,39 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
edit_helpers.installTemplate('publish-xblock');
|
||||
edit_helpers.installTemplate('publish-history');
|
||||
edit_helpers.installTemplate('unit-outline');
|
||||
edit_helpers.installTemplate('container-message');
|
||||
appendSetFixtures(mockContainerPage);
|
||||
});
|
||||
|
||||
model = new XBlockInfo({
|
||||
id: 'locator-container',
|
||||
display_name: 'Test Container',
|
||||
category: 'vertical',
|
||||
published: false,
|
||||
has_changes: false
|
||||
}, {
|
||||
parse: true
|
||||
});
|
||||
defaultXBlockInfo = {
|
||||
id: 'locator-container',
|
||||
display_name: 'Test Container',
|
||||
category: 'vertical',
|
||||
published: false,
|
||||
has_changes: false,
|
||||
edited_on: "Jul 02, 2014 at 14:20 UTC", edited_by: "joe",
|
||||
published_on: "Jul 01, 2014 at 12:45 UTC", published_by: "amako",
|
||||
visible_to_staff_only: false,
|
||||
currently_visible_to_students: false
|
||||
};
|
||||
|
||||
createXBlockInfo = function(options) {
|
||||
return _.extend(_.extend({}, defaultXBlockInfo), options || {});
|
||||
};
|
||||
|
||||
createContainerPage = function (test, options) {
|
||||
requests = create_sinon.requests(test);
|
||||
model = new XBlockInfo(createXBlockInfo(options), { parse: true });
|
||||
containerPage = new ContainerPage({
|
||||
model: model,
|
||||
templates: edit_helpers.mockComponentTemplates,
|
||||
el: $('#content'),
|
||||
isUnitPage: true
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
renderContainerPage = function(html, that) {
|
||||
requests = create_sinon.requests(that);
|
||||
renderContainerPage = function (test, html, options) {
|
||||
createContainerPage(test, options);
|
||||
containerPage.render();
|
||||
respondWithHtml(html);
|
||||
};
|
||||
@@ -57,6 +70,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
};
|
||||
|
||||
fetch = function (json) {
|
||||
json = createXBlockInfo(json);
|
||||
model.fetch();
|
||||
respondWithJson(json);
|
||||
};
|
||||
@@ -66,30 +80,30 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
previewCss = '.button-preview';
|
||||
|
||||
it('renders correctly for private unit', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
expect(containerPage.$(viewPublishedCss)).toHaveClass(disabledCss);
|
||||
expect(containerPage.$(previewCss)).not.toHaveClass(disabledCss);
|
||||
});
|
||||
|
||||
it('updates when published attribute changes', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({"id": "locator-container", "published": true});
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published": true});
|
||||
expect(containerPage.$(viewPublishedCss)).not.toHaveClass(disabledCss);
|
||||
|
||||
fetch({"id": "locator-container", "published": false});
|
||||
fetch({"published": false});
|
||||
expect(containerPage.$(viewPublishedCss)).toHaveClass(disabledCss);
|
||||
});
|
||||
|
||||
it('updates when has_changes attribute changes', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({"id": "locator-container", "has_changes": true});
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"has_changes": true});
|
||||
expect(containerPage.$(previewCss)).not.toHaveClass(disabledCss);
|
||||
|
||||
fetch({"id": "locator-container", "published": true, "has_changes": false});
|
||||
fetch({"published": true, "has_changes": false});
|
||||
expect(containerPage.$(previewCss)).toHaveClass(disabledCss);
|
||||
|
||||
// If published is false, preview is always enabled.
|
||||
fetch({"id": "locator-container", "published": false, "has_changes": false});
|
||||
fetch({"published": false, "has_changes": false});
|
||||
expect(containerPage.$(previewCss)).not.toHaveClass(disabledCss);
|
||||
});
|
||||
});
|
||||
@@ -97,21 +111,21 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
describe("Publisher", function () {
|
||||
var headerCss = '.pub-status',
|
||||
bitPublishingCss = "div.bit-publishing",
|
||||
publishedBit = "published",
|
||||
draftBit = "draft",
|
||||
publishedBit = "is-published",
|
||||
draftBit = "is-draft",
|
||||
staffOnlyBit = "is-staff-only",
|
||||
publishButtonCss = ".action-publish",
|
||||
discardChangesButtonCss = ".action-discard",
|
||||
lastDraftCss = ".wrapper-last-draft",
|
||||
releaseDateTitleCss = ".wrapper-release .title",
|
||||
releaseDateContentCss = ".wrapper-release .copy",
|
||||
lastRequest, promptSpies, sendDiscardChangesToServer;
|
||||
promptSpies, sendDiscardChangesToServer;
|
||||
|
||||
lastRequest = function() { return requests[requests.length - 1]; };
|
||||
|
||||
sendDiscardChangesToServer = function(test) {
|
||||
sendDiscardChangesToServer = function() {
|
||||
// Helper function to do the discard operation, up until the server response.
|
||||
renderContainerPage(mockContainerXBlockHtml, test);
|
||||
fetch({"id": "locator-container", "published": true, "has_changes": true});
|
||||
containerPage.render();
|
||||
respondWithHtml(mockContainerXBlockHtml);
|
||||
fetch({"published": true, "has_changes": true});
|
||||
expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled');
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(draftBit);
|
||||
// Click discard changes
|
||||
@@ -132,30 +146,30 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
});
|
||||
|
||||
it('renders correctly with private content', function () {
|
||||
var verifyPrivateState = function(){
|
||||
// State is the same regardless of "has_changes" value.
|
||||
expect(containerPage.$(headerCss).text()).toContain('Draft (Unpublished changes)');
|
||||
var verifyPrivateState = function() {
|
||||
expect(containerPage.$(headerCss).text()).toContain('Draft (Never published)');
|
||||
expect(containerPage.$(publishButtonCss)).not.toHaveClass(disabledCss);
|
||||
expect(containerPage.$(discardChangesButtonCss)).toHaveClass(disabledCss);
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(draftBit);
|
||||
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(draftBit);
|
||||
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(publishedBit);
|
||||
};
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({"id": "locator-container", "published": false, "has_changes": false});
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published": false, "has_changes": false});
|
||||
verifyPrivateState();
|
||||
|
||||
fetch({"id": "locator-container", "published": false, "has_changes": true});
|
||||
fetch({"published": false, "has_changes": true});
|
||||
verifyPrivateState();
|
||||
});
|
||||
|
||||
it('renders correctly with public content', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({"id": "locator-container", "published": true, "has_changes": false});
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published": true, "has_changes": false});
|
||||
expect(containerPage.$(headerCss).text()).toContain('Published');
|
||||
expect(containerPage.$(publishButtonCss)).toHaveClass(disabledCss);
|
||||
expect(containerPage.$(discardChangesButtonCss)).toHaveClass(disabledCss);
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(publishedBit);
|
||||
|
||||
fetch({"id": "locator-container", "published": true, "has_changes": true});
|
||||
fetch({"published": true, "has_changes": true});
|
||||
expect(containerPage.$(headerCss).text()).toContain('Draft (Unpublished changes)');
|
||||
expect(containerPage.$(publishButtonCss)).not.toHaveClass(disabledCss);
|
||||
expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass(disabledCss);
|
||||
@@ -164,9 +178,10 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
|
||||
it('can publish private content', function () {
|
||||
var notificationSpy = edit_helpers.createNotificationSpy();
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({"id": "locator-container", "published": false, "has_changes": false});
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(draftBit);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published": false, "has_changes": false});
|
||||
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(draftBit);
|
||||
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(publishedBit);
|
||||
|
||||
// Click publish
|
||||
containerPage.$(publishButtonCss).click();
|
||||
@@ -191,9 +206,9 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
});
|
||||
|
||||
it('can does not fetch if publish fails', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({"id": "locator-container", "published": false, "has_changes": false});
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(draftBit);
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published": false});
|
||||
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(publishedBit);
|
||||
|
||||
// Click publish
|
||||
containerPage.$(publishButtonCss).click();
|
||||
@@ -205,17 +220,18 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
expect(requests.length).toEqual(numRequests);
|
||||
|
||||
// Verify still in draft state.
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(draftBit);
|
||||
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(publishedBit);
|
||||
// Verify that the "published" value has been cleared out of the model.
|
||||
expect(containerPage.model.get("publish")).toBeNull();
|
||||
});
|
||||
|
||||
it('can discard changes', function () {
|
||||
var notificationSpy = edit_helpers.createNotificationSpy(),
|
||||
renderPageSpy = spyOn(containerPage.xblockPublisher, 'renderPage').andCallThrough(),
|
||||
numRequests;
|
||||
var notificationSpy, renderPageSpy, numRequests;
|
||||
createContainerPage(this);
|
||||
notificationSpy = edit_helpers.createNotificationSpy();
|
||||
renderPageSpy = spyOn(containerPage.xblockPublisher, 'renderPage').andCallThrough();
|
||||
|
||||
sendDiscardChangesToServer(this);
|
||||
sendDiscardChangesToServer();
|
||||
numRequests = requests.length;
|
||||
|
||||
// Respond with success.
|
||||
@@ -230,10 +246,11 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
});
|
||||
|
||||
it('does not fetch if discard changes fails', function () {
|
||||
var renderPageSpy = spyOn(containerPage.xblockPublisher, 'renderPage').andCallThrough(),
|
||||
numRequests;
|
||||
var renderPageSpy, numRequests;
|
||||
createContainerPage(this);
|
||||
renderPageSpy = spyOn(containerPage.xblockPublisher, 'renderPage').andCallThrough();
|
||||
|
||||
sendDiscardChangesToServer(this);
|
||||
sendDiscardChangesToServer();
|
||||
numRequests = requests.length;
|
||||
|
||||
// Respond with failure
|
||||
@@ -246,8 +263,8 @@ 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});
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published": true, "has_changes": true});
|
||||
var numRequests = requests.length;
|
||||
|
||||
// Click discard changes
|
||||
@@ -262,84 +279,213 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
|
||||
});
|
||||
|
||||
it('renders the last published date and user when there are no changes', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({ "id": "locator-container", "has_changes": false,
|
||||
"edited_on": "Jun 30, 2014 at 14:20 UTC", "edited_by": "joe",
|
||||
"published_on": "Jul 01, 2014 at 12:45 UTC", "published_by": "amako"});
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published_on": "Jul 01, 2014 at 12:45 UTC", "published_by": "amako"});
|
||||
expect(containerPage.$(lastDraftCss).text()).
|
||||
toContain("Last published Jul 01, 2014 at 12:45 UTC by amako");
|
||||
});
|
||||
|
||||
it('renders the last saved date and user when there are changes', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({ "id": "locator-container", "has_changes": true,
|
||||
"edited_on": "Jul 02, 2014 at 14:20 UTC", "edited_by": "joe",
|
||||
"published_on": "Jul 01, 2014 at 12:45 UTC", "published_by": "amako"});
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"has_changes": true, "edited_on": "Jul 02, 2014 at 14:20 UTC", "edited_by": "joe"});
|
||||
expect(containerPage.$(lastDraftCss).text()).
|
||||
toContain("Draft saved on Jul 02, 2014 at 14:20 UTC by joe");
|
||||
});
|
||||
|
||||
it('renders the release date correctly when unreleased', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({ "id": "locator-container", "published": true, "released_to_students": false,
|
||||
"release_date": "Jul 02, 2014 at 14:20 UTC", "release_date_from": 'Section "Week 1"'});
|
||||
expect(containerPage.$(releaseDateTitleCss).text()).toContain("Scheduled:");
|
||||
expect(containerPage.$(releaseDateContentCss).text()).
|
||||
toContain('Jul 02, 2014 at 14:20 UTC with Section "Week 1"');
|
||||
describe("Release Date", function() {
|
||||
it('renders correctly when unreleased', function () {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published": true, "released_to_students": false,
|
||||
"release_date": "Jul 02, 2014 at 14:20 UTC", "release_date_from": 'Section "Week 1"'});
|
||||
expect(containerPage.$(releaseDateTitleCss).text()).toContain("Scheduled:");
|
||||
expect(containerPage.$(releaseDateContentCss).text()).
|
||||
toContain('Jul 02, 2014 at 14:20 UTC with Section "Week 1"');
|
||||
});
|
||||
|
||||
it('renders correctly when released', function () {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published": true, "released_to_students": true,
|
||||
"release_date": "Jul 02, 2014 at 14:20 UTC", "release_date_from": 'Section "Week 1"' });
|
||||
expect(containerPage.$(releaseDateTitleCss).text()).toContain("Released:");
|
||||
expect(containerPage.$(releaseDateContentCss).text()).
|
||||
toContain('Jul 02, 2014 at 14:20 UTC with Section "Week 1"');
|
||||
});
|
||||
|
||||
it('renders correctly when the release date is not set', function () {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published": true, "released_to_students": false,
|
||||
"release_date": null, "release_date_from": null });
|
||||
expect(containerPage.$(releaseDateTitleCss).text()).toContain("Release:");
|
||||
expect(containerPage.$(releaseDateContentCss).text()).toContain("Unscheduled");
|
||||
});
|
||||
|
||||
it('renders correctly when the unit is not published', function () {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({"published": false, "released_to_students": true,
|
||||
"release_date": "Jul 02, 2014 at 14:20 UTC", "release_date_from": 'Section "Week 1"' });
|
||||
// Force a render because none of the fetched fields will trigger a render
|
||||
containerPage.xblockPublisher.render();
|
||||
expect(containerPage.$(releaseDateTitleCss).text()).toContain("Release:");
|
||||
expect(containerPage.$(releaseDateContentCss).text()).
|
||||
toContain('Jul 02, 2014 at 14:20 UTC with Section "Week 1"');
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the release date correctly when released', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({ "id": "locator-container", "published": true, "released_to_students": true,
|
||||
"release_date": "Jul 02, 2014 at 14:20 UTC", "release_date_from": 'Section "Week 1"' });
|
||||
expect(containerPage.$(releaseDateTitleCss).text()).toContain("Released:");
|
||||
expect(containerPage.$(releaseDateContentCss).text()).
|
||||
toContain('Jul 02, 2014 at 14:20 UTC with Section "Week 1"');
|
||||
});
|
||||
describe("Content Visibility", function () {
|
||||
var requestStaffOnly, verifyStaffOnly, promptSpy;
|
||||
|
||||
it('renders the release date correctly when the release date is not set', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({ "id": "locator-container", "published": true, "released_to_students": false,
|
||||
"release_date": null, "release_date_from": null });
|
||||
expect(containerPage.$(releaseDateTitleCss).text()).toContain("Release:");
|
||||
expect(containerPage.$(releaseDateContentCss).text()).toContain("Unscheduled");
|
||||
});
|
||||
requestStaffOnly = function(isStaffOnly) {
|
||||
containerPage.$('.action-staff-lock').click();
|
||||
|
||||
it('renders the release date correctly when the unit is not published', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({ "id": "locator-container", "published": false, "released_to_students": true,
|
||||
"release_date": "Jul 02, 2014 at 14:20 UTC", "release_date_from": 'Section "Week 1"' });
|
||||
// Force a render because none of the fetched fields will trigger a render
|
||||
containerPage.xblockPublisher.render();
|
||||
expect(containerPage.$(releaseDateTitleCss).text()).toContain("Release:");
|
||||
expect(containerPage.$(releaseDateContentCss).text()).
|
||||
toContain('Jul 02, 2014 at 14:20 UTC with Section "Week 1"');
|
||||
// If removing the staff lock, click 'Yes' to confirm
|
||||
if (!isStaffOnly) {
|
||||
edit_helpers.confirmPrompt(promptSpy);
|
||||
}
|
||||
|
||||
create_sinon.expectJsonRequest(requests, 'POST', '/xblock/locator-container', {
|
||||
publish: 'republish',
|
||||
metadata: { visible_to_staff_only: isStaffOnly }
|
||||
});
|
||||
create_sinon.respondWithJson(requests, {
|
||||
data: null,
|
||||
id: "locator-container",
|
||||
metadata: {
|
||||
visible_to_staff_only: isStaffOnly
|
||||
}
|
||||
});
|
||||
create_sinon.expectJsonRequest(requests, 'GET', '/xblock/locator-container');
|
||||
create_sinon.respondWithJson(requests, createXBlockInfo({
|
||||
published: containerPage.model.get('published'),
|
||||
visible_to_staff_only: isStaffOnly
|
||||
}));
|
||||
};
|
||||
|
||||
verifyStaffOnly = function(isStaffOnly) {
|
||||
if (isStaffOnly) {
|
||||
expect(containerPage.$('.action-staff-lock i')).toHaveClass('icon-check');
|
||||
expect(containerPage.$('.wrapper-visibility .copy').text()).toBe('Staff Only');
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(staffOnlyBit);
|
||||
} else {
|
||||
expect(containerPage.$('.action-staff-lock i')).toHaveClass('icon-check-empty');
|
||||
expect(containerPage.$('.wrapper-visibility .copy').text()).toBe('Staff and Students');
|
||||
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(staffOnlyBit);
|
||||
}
|
||||
};
|
||||
|
||||
it("is initially shown to all", function() {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
verifyStaffOnly(false);
|
||||
});
|
||||
|
||||
it("can be set to staff only", function() {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
containerPage.$('.action-staff-lock').click();
|
||||
requestStaffOnly(true);
|
||||
verifyStaffOnly(true);
|
||||
});
|
||||
|
||||
it("can remove staff only setting", function() {
|
||||
promptSpy = edit_helpers.createPromptSpy();
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
requestStaffOnly(true);
|
||||
requestStaffOnly(false);
|
||||
verifyStaffOnly(false);
|
||||
expect(containerPage.$(bitPublishingCss)).not.toHaveClass(publishedBit);
|
||||
});
|
||||
|
||||
it("can remove staff only setting from published unit", function() {
|
||||
promptSpy = edit_helpers.createPromptSpy();
|
||||
renderContainerPage(this, mockContainerXBlockHtml, { published: true });
|
||||
requestStaffOnly(true);
|
||||
requestStaffOnly(false);
|
||||
verifyStaffOnly(false);
|
||||
expect(containerPage.$(bitPublishingCss)).toHaveClass(publishedBit);
|
||||
});
|
||||
|
||||
it("does not refresh if removing staff only is canceled", function() {
|
||||
var requestCount;
|
||||
promptSpy = edit_helpers.createPromptSpy();
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
requestStaffOnly(true);
|
||||
requestCount = requests.length;
|
||||
containerPage.$('.action-staff-lock').click();
|
||||
edit_helpers.confirmPrompt(promptSpy, true); // Click 'No' to cancel
|
||||
expect(requests.length).toBe(requestCount);
|
||||
verifyStaffOnly(true);
|
||||
});
|
||||
|
||||
it("does not refresh when failing to set staff only", function() {
|
||||
var requestCount;
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
containerPage.$('.lock-checkbox').click();
|
||||
requestCount = requests.length;
|
||||
create_sinon.respondWithError(requests);
|
||||
expect(requests.length).toBe(requestCount);
|
||||
verifyStaffOnly(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("PublishHistory", function () {
|
||||
var lastPublishCss = ".wrapper-last-publish";
|
||||
|
||||
it('renders the last published date and user when the block is published', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({ "id": "locator-container", "published": true,
|
||||
"published_on": "Jul 01, 2014 at 12:45 UTC", "published_by": "amako" });
|
||||
it('renders the last published date and user when the block is published', function() {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({
|
||||
"published": true, "published_on": "Jul 01, 2014 at 12:45 UTC", "published_by": "amako"
|
||||
});
|
||||
expect(containerPage.$(lastPublishCss).text()).
|
||||
toContain("Last published Jul 01, 2014 at 12:45 UTC by amako");
|
||||
});
|
||||
|
||||
it('renders never published when the block is unpublished', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({ "id": "locator-container", "published": false,
|
||||
"published_on": "Jul 01, 2014 at 12:45 UTC", "published_by": "amako" });
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({ "published": false });
|
||||
expect(containerPage.$(lastPublishCss).text()).toContain("Never published");
|
||||
});
|
||||
|
||||
it('renders correctly when the block is published without publish info', function () {
|
||||
renderContainerPage(mockContainerXBlockHtml, this);
|
||||
fetch({ "id": "locator-container", "published": true, "published_on": null, "published_by": null});
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({
|
||||
"published": true, "published_on": null, "published_by": null
|
||||
});
|
||||
expect(containerPage.$(lastPublishCss).text()).toContain("Previously published");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Message Area", function() {
|
||||
var messageSelector = '.container-message .warning',
|
||||
warningMessage = 'This content is live for students. Edit with caution.';
|
||||
|
||||
it('is empty for a unit that is not currently visible to students', function() {
|
||||
renderContainerPage(this, mockContainerXBlockHtml, {
|
||||
currently_visible_to_students: false
|
||||
});
|
||||
expect(containerPage.$(messageSelector).text().trim()).toBe('');
|
||||
});
|
||||
|
||||
it('shows a message for a unit that is currently visible to students', function() {
|
||||
renderContainerPage(this, mockContainerXBlockHtml, {
|
||||
currently_visible_to_students: true
|
||||
});
|
||||
expect(containerPage.$(messageSelector).text().trim()).toBe(warningMessage);
|
||||
});
|
||||
|
||||
it('hides the message when the unit is hidden from students', function() {
|
||||
renderContainerPage(this, mockContainerXBlockHtml, {
|
||||
currently_visible_to_students: true
|
||||
});
|
||||
fetch({ currently_visible_to_students: false });
|
||||
expect(containerPage.$(messageSelector).text().trim()).toBe('');
|
||||
});
|
||||
|
||||
it('shows a message when a unit is made visible', function() {
|
||||
renderContainerPage(this, mockContainerXBlockHtml, {
|
||||
currently_visible_to_students: false
|
||||
});
|
||||
fetch({ currently_visible_to_students: true });
|
||||
expect(containerPage.$(messageSelector).text().trim()).toBe(warningMessage);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,6 +29,11 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
|
||||
model: this.model,
|
||||
view: this.view
|
||||
});
|
||||
this.messageView = new ContainerSubviews.MessageView({
|
||||
el: this.$('.container-message'),
|
||||
model: this.model
|
||||
});
|
||||
this.messageView.render();
|
||||
this.isUnitPage = this.options.isUnitPage;
|
||||
if (this.isUnitPage) {
|
||||
this.xblockPublisher = new ContainerSubviews.Publisher({
|
||||
|
||||
@@ -10,7 +10,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
* A view that calls render when "has_changes" or "published" values in XBlockInfo have changed
|
||||
* after a server sync operation.
|
||||
*/
|
||||
var UnitStateListenerView = BaseView.extend({
|
||||
var ContainerStateListenerView = BaseView.extend({
|
||||
|
||||
// takes XBlockInfo as a model
|
||||
initialize: function() {
|
||||
@@ -18,18 +18,43 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
},
|
||||
|
||||
onSync: function(model) {
|
||||
if (ViewUtils.hasChangedAttributes(model, ['has_changes', 'published'])) {
|
||||
if (this.shouldRefresh(model)) {
|
||||
this.render();
|
||||
}
|
||||
},
|
||||
|
||||
shouldRefresh: function(model) {
|
||||
return false;
|
||||
},
|
||||
|
||||
render: function() {}
|
||||
});
|
||||
|
||||
var MessageView = ContainerStateListenerView.extend({
|
||||
initialize: function () {
|
||||
ContainerStateListenerView.prototype.initialize.call(this);
|
||||
this.template = this.loadTemplate('container-message');
|
||||
},
|
||||
|
||||
shouldRefresh: function(model) {
|
||||
return ViewUtils.hasChangedAttributes(model, ['currently_visible_to_students']);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.html(this.template({
|
||||
currentlyVisibleToStudents: this.model.get('currently_visible_to_students')
|
||||
}));
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* A controller for updating the "View Live" and "Preview" buttons.
|
||||
*/
|
||||
var PreviewActionController = UnitStateListenerView.extend({
|
||||
var PreviewActionController = ContainerStateListenerView.extend({
|
||||
shouldRefresh: function(model) {
|
||||
return ViewUtils.hasChangedAttributes(model, ['has_changes', 'published']);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var previewAction = this.$el.find('.button-preview'),
|
||||
@@ -59,7 +84,8 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
var Publisher = BaseView.extend({
|
||||
events: {
|
||||
'click .action-publish': 'publish',
|
||||
'click .action-discard': 'discardChanges'
|
||||
'click .action-discard': 'discardChanges',
|
||||
'click .action-staff-lock': 'toggleStaffLock'
|
||||
},
|
||||
|
||||
// takes XBlockInfo as a model
|
||||
@@ -72,22 +98,25 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
},
|
||||
|
||||
onSync: function(model) {
|
||||
if (ViewUtils.hasChangedAttributes(model, ['has_changes', 'published', 'edited_on', 'edited_by'])) {
|
||||
if (ViewUtils.hasChangedAttributes(model, [
|
||||
'has_changes', 'published', 'edited_on', 'edited_by', 'visible_to_staff_only'
|
||||
])) {
|
||||
this.render();
|
||||
}
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.html(this.template({
|
||||
has_changes: this.model.get('has_changes'),
|
||||
hasChanges: this.model.get('has_changes'),
|
||||
published: this.model.get('published'),
|
||||
edited_on: this.model.get('edited_on'),
|
||||
edited_by: this.model.get('edited_by'),
|
||||
published_on: this.model.get('published_on'),
|
||||
published_by: this.model.get('published_by'),
|
||||
released_to_students: this.model.get('released_to_students'),
|
||||
release_date: this.model.get('release_date'),
|
||||
release_date_from: this.model.get('release_date_from')
|
||||
editedOn: this.model.get('edited_on'),
|
||||
editedBy: this.model.get('edited_by'),
|
||||
publishedOn: this.model.get('published_on'),
|
||||
publishedBy: this.model.get('published_by'),
|
||||
releasedToStudents: this.model.get('released_to_students'),
|
||||
releaseDate: this.model.get('release_date'),
|
||||
releaseDateFrom: this.model.get('release_date_from'),
|
||||
visibleToStaffOnly: this.model.get('visible_to_staff_only')
|
||||
}));
|
||||
|
||||
return this;
|
||||
@@ -127,10 +156,60 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
toggleStaffLock: function (e) {
|
||||
var xblockInfo = this.model, self=this, enableStaffLock,
|
||||
saveAndPublishStaffLock, revertCheckBox;
|
||||
if (e && e.preventDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
enableStaffLock = !xblockInfo.get('visible_to_staff_only');
|
||||
|
||||
revertCheckBox = function() {
|
||||
self.checkStaffLock(!enableStaffLock);
|
||||
};
|
||||
|
||||
saveAndPublishStaffLock = function() {
|
||||
return xblockInfo.save({
|
||||
publish: 'republish',
|
||||
metadata: {visible_to_staff_only: enableStaffLock}},
|
||||
{patch: true}
|
||||
).always(function() {
|
||||
xblockInfo.set("publish", null);
|
||||
}).done(function () {
|
||||
xblockInfo.fetch();
|
||||
}).fail(function() {
|
||||
revertCheckBox();
|
||||
});
|
||||
};
|
||||
|
||||
this.checkStaffLock(enableStaffLock);
|
||||
if (enableStaffLock) {
|
||||
ViewUtils.runOperationShowingMessage(gettext('Setting Staff Lock…'),
|
||||
_.bind(saveAndPublishStaffLock, self));
|
||||
} else {
|
||||
ViewUtils.confirmThenRunOperation(gettext("Remove Staff Lock"),
|
||||
gettext("Are you sure you want to remove the staff lock? Once you publish this unit, it will be released to students on the release date."),
|
||||
gettext("Remove Staff Lock"),
|
||||
function() {
|
||||
ViewUtils.runOperationShowingMessage(gettext('Removing Staff Lock…'),
|
||||
_.bind(saveAndPublishStaffLock, self));
|
||||
},
|
||||
function() {
|
||||
// On cancel, revert the check in the check box
|
||||
revertCheckBox();
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
checkStaffLock: function(check) {
|
||||
this.$('.action-staff-lock i').removeClass('icon-check icon-check-empty');
|
||||
this.$('.action-staff-lock i').addClass(check ? 'icon-check' : 'icon-check-empty');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* PublishHistory displays when and by whom the xblock was last published, if it ever was.
|
||||
*/
|
||||
@@ -161,6 +240,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
});
|
||||
|
||||
return {
|
||||
'MessageView': MessageView,
|
||||
'PreviewActionController': PreviewActionController,
|
||||
'Publisher': Publisher,
|
||||
'PublishHistory': PublishHistory
|
||||
|
||||
@@ -33,7 +33,7 @@ define(["jquery", "underscore", "gettext", "js/views/feedback_notification", "js
|
||||
/**
|
||||
* Confirms with the user whether to run an operation or not, and then runs it if desired.
|
||||
*/
|
||||
confirmThenRunOperation = function(title, message, actionLabel, operation) {
|
||||
confirmThenRunOperation = function(title, message, actionLabel, operation, onCancelCallback) {
|
||||
return new PromptView.Warning({
|
||||
title: title,
|
||||
message: message,
|
||||
@@ -48,6 +48,9 @@ define(["jquery", "underscore", "gettext", "js/views/feedback_notification", "js
|
||||
secondary: {
|
||||
text: gettext('Cancel'),
|
||||
click: function(prompt) {
|
||||
if (onCancelCallback) {
|
||||
onCancelCallback();
|
||||
}
|
||||
return prompt.hide();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user