Commit 572b4fc0 by Ben McMorran Committed by cahrens

Displays the date, time, and username of the most recent save and publish

Conflicts:
	cms/djangoapps/contentstore/views/item.py
parent 7cb5c4d7
...@@ -566,8 +566,10 @@ def create_xblock_info(usage_key, xblock, data=None, metadata=None): ...@@ -566,8 +566,10 @@ def create_xblock_info(usage_key, xblock, data=None, metadata=None):
"category": xblock.category, "category": xblock.category,
"has_changes": modulestore().has_changes(usage_key), "has_changes": modulestore().has_changes(usage_key),
"published": publish_state in (PublishState.public, PublishState.draft), "published": publish_state in (PublishState.public, PublishState.draft),
"edited_on": get_default_time_display(xblock.edited_on) if xblock.edited_on else None, "edited_on": get_default_time_display(xblock.subtree_edited_on) if xblock.subtree_edited_on else None,
"edited_by": safe_get_username(xblock.edited_by) "edited_by": safe_get_username(xblock.subtree_edited_by),
"published_on": get_default_time_display(xblock.published_date) if xblock.published_date else None,
"published_by": safe_get_username(xblock.published_by),
} }
if data is not None: if data is not None:
xblock_info["data"] = data xblock_info["data"] = data
......
...@@ -32,15 +32,22 @@ define(["backbone", "js/utils/module"], function(Backbone, ModuleUtils) { ...@@ -32,15 +32,22 @@ define(["backbone", "js/utils/module"], function(Backbone, ModuleUtils) {
*/ */
"locked": null, "locked": null,
/** /**
* Date of last edit to this xblock. Will be the latest change to either the draft * Date of the last edit to this xblock or any of its descendants.
* or the published version.
*/ */
"edited_on":null, "edited_on":null,
/** /**
* User who last edited the xblock. * User who last edited the xblock or any of its descendants.
*/ */
"edited_by":null, "edited_by":null,
/** /**
* Date of the last publish of this xblock, or null if never published.
*/
"published_on": null,
/**
* User who last published the xblock, or null if never published.
*/
"published_by": null,
/**
* If the xblock is published, the date on which it will be released to students. * If the xblock is published, the date on which it will be released to students.
*/ */
"release_date": null, "release_date": null,
......
...@@ -12,6 +12,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -12,6 +12,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
beforeEach(function () { beforeEach(function () {
edit_helpers.installTemplate('xblock-string-field-editor'); edit_helpers.installTemplate('xblock-string-field-editor');
edit_helpers.installTemplate('publish-xblock'); edit_helpers.installTemplate('publish-xblock');
edit_helpers.installTemplate('publish-history');
appendSetFixtures(mockContainerPage); appendSetFixtures(mockContainerPage);
model = new XBlockInfo({ model = new XBlockInfo({
...@@ -130,6 +131,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -130,6 +131,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
draftBit = "draft", draftBit = "draft",
publishButtonCss = ".action-publish", publishButtonCss = ".action-publish",
discardChangesButtonCss = ".action-discard", discardChangesButtonCss = ".action-discard",
lastDraftCss = ".wrapper-last-draft",
request, lastRequest, promptSpies, sendDiscardChangesToServer; request, lastRequest, promptSpies, sendDiscardChangesToServer;
lastRequest = function() { return requests[requests.length - 1]; }; lastRequest = function() { return requests[requests.length - 1]; };
...@@ -280,6 +282,49 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin ...@@ -280,6 +282,49 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
expect(requests.length).toEqual(numRequests); expect(requests.length).toEqual(numRequests);
expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled'); expect(containerPage.$(discardChangesButtonCss)).not.toHaveClass('is-disabled');
}); });
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"});
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"});
expect(containerPage.$(lastDraftCss).text()).
toContain("Draft saved on Jul 02, 2014 at 14:20 UTC by joe");
});
});
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" });
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" });
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});
expect(containerPage.$(lastPublishCss).text()).toContain("Previously published");
});
}); });
}); });
}); });
...@@ -34,6 +34,12 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/contai ...@@ -34,6 +34,12 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/contai
}); });
this.xblockPublisher.render(); this.xblockPublisher.render();
this.publishHistory = new ContainerSubviews.PublishHistory({
el: this.$('#publish-history'),
model: this.model
});
this.publishHistory.render();
// No need to render initially. This is only used for updating state // No need to render initially. This is only used for updating state
// when the unit changes visibility. // when the unit changes visibility.
this.visibilityState = new ContainerSubviews.VisibilityStateController({ this.visibilityState = new ContainerSubviews.VisibilityStateController({
......
...@@ -108,7 +108,9 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/feedba ...@@ -108,7 +108,9 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/feedba
has_changes: this.model.get('has_changes'), has_changes: this.model.get('has_changes'),
published: this.model.get('published'), published: this.model.get('published'),
edited_on: this.model.get('edited_on'), edited_on: this.model.get('edited_on'),
edited_by: this.model.get('edited_by') edited_by: this.model.get('edited_by'),
published_on: this.model.get('published_on'),
published_by: this.model.get('published_by')
})); }));
return this; return this;
...@@ -174,9 +176,40 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/feedba ...@@ -174,9 +176,40 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/feedba
} }
}); });
/**
* PublishHistory displays when and by whom the xblock was last published, if it ever was.
*/
var PublishHistory = BaseView.extend({
// takes XBlockInfo as a model
initialize: function () {
BaseView.prototype.initialize.call(this);
this.template = this.loadTemplate('publish-history');
this.model.on('sync', this.onSync, this);
},
onSync: function(e) {
if (e.changedAttributes() && (('published' in e.changedAttributes()) ||
('published_on' in e.changedAttributes()) || ('published_by' in e.changedAttributes()))) {
this.render();
}
},
render: function () {
this.$el.html(this.template({
published: this.model.get('published'),
published_on: this.model.get('published_on'),
published_by: this.model.get('published_by')
}));
return this;
}
});
return { return {
'VisibilityStateController': VisibilityStateController, 'VisibilityStateController': VisibilityStateController,
'PreviewActionController': PreviewActionController, 'PreviewActionController': PreviewActionController,
'Publisher': Publisher 'Publisher': Publisher,
'PublishHistory': PublishHistory
}; };
}); // end define(); }); // end define();
...@@ -139,6 +139,11 @@ ...@@ -139,6 +139,11 @@
.wrapper-last-draft { .wrapper-last-draft {
padding: ($baseline*.75) ($baseline*.75) ($baseline/4) ($baseline*.75); padding: ($baseline*.75) ($baseline*.75) ($baseline/4) ($baseline*.75);
.date,
.user {
font-weight: 600;
}
} }
.wrapper-release { .wrapper-release {
...@@ -184,6 +189,26 @@ ...@@ -184,6 +189,26 @@
} }
// versioning widget
.unit-publish-history {
.wrapper-last-publish {
margin-bottom: $baseline;
padding: ($baseline*.75);
background-color: $white;
.copy {
@extend %t-copy-sub2;
color: $gray;
}
.date,
.user {
font-weight: 600;
}
}
}
// location widget // location widget
.unit-location { .unit-location {
@extend %bar-module; @extend %bar-module;
......
...@@ -24,7 +24,7 @@ from django.utils.translation import ugettext as _ ...@@ -24,7 +24,7 @@ from django.utils.translation import ugettext as _
templates = ["basic-modal", "modal-button", "edit-xblock-modal", templates = ["basic-modal", "modal-button", "edit-xblock-modal",
"editor-mode-button", "upload-dialog", "image-modal", "editor-mode-button", "upload-dialog", "image-modal",
"add-xblock-component", "add-xblock-component-button", "add-xblock-component-menu", "add-xblock-component", "add-xblock-component-button", "add-xblock-component-menu",
"add-xblock-component-menu-problem", "xblock-string-field-editor", "publish-xblock"] "add-xblock-component-menu-problem", "xblock-string-field-editor", "publish-xblock", "publish-history"]
%> %>
<%block name="header_extras"> <%block name="header_extras">
% for template_name in templates: % for template_name in templates:
...@@ -142,6 +142,7 @@ templates = ["basic-modal", "modal-button", "edit-xblock-modal", ...@@ -142,6 +142,7 @@ templates = ["basic-modal", "modal-button", "edit-xblock-modal",
% endif % endif
% if is_unit_page: % if is_unit_page:
<div id="publish-unit"></div> <div id="publish-unit"></div>
<div id="publish-history" class="unit-publish-history"></div>
<div class="unit-location is-hidden"> <div class="unit-location is-hidden">
<h4 class="bar-mod-title">${_("Unit Location")}</h4> <h4 class="bar-mod-title">${_("Unit Location")}</h4>
<div class="wrapper-unit-id bar-mod-content"> <div class="wrapper-unit-id bar-mod-content">
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
</article> </article>
<aside class="content-supplementary" role="complimentary"> <aside class="content-supplementary" role="complimentary">
<div id="publish-unit" class="window"></div> <div id="publish-unit" class="window"></div>
<div id="publish-history"></div>
</aside> </aside>
<div class="unit-location"> <div class="unit-location">
<h4 class="header">${_("Unit Location")}</h4> <h4 class="header">${_("Unit Location")}</h4>
......
<div class="wrapper-last-publish">
<p class="copy">
<% if (published) {
if (published_on && published_by) {
var message = gettext("Last published %(last_published_date)s by %(publish_username)s"); %>
<%= interpolate(message, {
last_published_date: '<span class="date">' + published_on + '</span>',
publish_username: '<span class="user">' + published_by + '</span>' }, true) %>
<% } else { %>
<%= gettext("Previously published") %>
<% } %>
<% } else { %>
<%= gettext("Never published") %>
<% } %>
</p>
</div>
\ No newline at end of file
...@@ -7,12 +7,23 @@ ...@@ -7,12 +7,23 @@
<% } %> <% } %>
</h3> </h3>
<!--To be added in STUDIO-1826--> <div class="wrapper-last-draft bar-mod-content">
<!--<div class="wrapper-last-draft bar-mod-content">--> <p class="copy meta">
<!--<p class="copy meta">--> <% if (has_changes && edited_on && edited_by) {
<!--Draft saved on 6/15/2014 at 12:45pm by amako--> var message = gettext("Draft saved on %(last_saved_date)s by %(edit_username)s") %>
<!--</p>--> <%= interpolate(message, {
<!--</div>--> last_saved_date: '<span class="date">' + edited_on + '</span>',
edit_username: '<span class="user">' + edited_by + '</span>' }, true) %>
<% } else if (published_on && published_by) {
var message = gettext("Last published %(last_published_date)s by %(publish_username)s"); %>
<%= interpolate(message, {
last_published_date: '<span class="date">' + published_on + '</span>',
publish_username: '<span class="user">' + published_by + '</span>' }, true) %>
<% } else { %>
<%= gettext("Previously published") %>
<% } %>
</p>
</div>
<!--To be added in STUD-1829--> <!--To be added in STUD-1829-->
<!--<div class="wrapper-release bar-mod-content">--> <!--<div class="wrapper-release bar-mod-content">-->
......
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