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):
"category": xblock.category,
"has_changes": modulestore().has_changes(usage_key),
"published": publish_state in (PublishState.public, PublishState.draft),
"edited_on": get_default_time_display(xblock.edited_on) if xblock.edited_on else None,
"edited_by": safe_get_username(xblock.edited_by)
"edited_on": get_default_time_display(xblock.subtree_edited_on) if xblock.subtree_edited_on else None,
"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:
xblock_info["data"] = data
......
......@@ -32,15 +32,22 @@ define(["backbone", "js/utils/module"], function(Backbone, ModuleUtils) {
*/
"locked": null,
/**
* Date of last edit to this xblock. Will be the latest change to either the draft
* or the published version.
* Date of the last edit to this xblock or any of its descendants.
*/
"edited_on":null,
/**
* User who last edited the xblock.
* User who last edited the xblock or any of its descendants.
*/
"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.
*/
"release_date": null,
......
......@@ -12,6 +12,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
beforeEach(function () {
edit_helpers.installTemplate('xblock-string-field-editor');
edit_helpers.installTemplate('publish-xblock');
edit_helpers.installTemplate('publish-history');
appendSetFixtures(mockContainerPage);
model = new XBlockInfo({
......@@ -130,6 +131,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
draftBit = "draft",
publishButtonCss = ".action-publish",
discardChangesButtonCss = ".action-discard",
lastDraftCss = ".wrapper-last-draft",
request, lastRequest, promptSpies, sendDiscardChangesToServer;
lastRequest = function() { return requests[requests.length - 1]; };
......@@ -280,6 +282,49 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
expect(requests.length).toEqual(numRequests);
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
});
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
// when the unit changes visibility.
this.visibilityState = new ContainerSubviews.VisibilityStateController({
......
......@@ -108,7 +108,9 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/feedba
has_changes: this.model.get('has_changes'),
published: this.model.get('published'),
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;
......@@ -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 {
'VisibilityStateController': VisibilityStateController,
'PreviewActionController': PreviewActionController,
'Publisher': Publisher
'Publisher': Publisher,
'PublishHistory': PublishHistory
};
}); // end define();
......@@ -139,6 +139,11 @@
.wrapper-last-draft {
padding: ($baseline*.75) ($baseline*.75) ($baseline/4) ($baseline*.75);
.date,
.user {
font-weight: 600;
}
}
.wrapper-release {
......@@ -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
.unit-location {
@extend %bar-module;
......
......@@ -24,7 +24,7 @@ from django.utils.translation import ugettext as _
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"]
"add-xblock-component-menu-problem", "xblock-string-field-editor", "publish-xblock", "publish-history"]
%>
<%block name="header_extras">
% for template_name in templates:
......@@ -142,6 +142,7 @@ templates = ["basic-modal", "modal-button", "edit-xblock-modal",
% endif
% if is_unit_page:
<div id="publish-unit"></div>
<div id="publish-history" class="unit-publish-history"></div>
<div class="unit-location is-hidden">
<h4 class="bar-mod-title">${_("Unit Location")}</h4>
<div class="wrapper-unit-id bar-mod-content">
......
......@@ -51,6 +51,7 @@
</article>
<aside class="content-supplementary" role="complimentary">
<div id="publish-unit" class="window"></div>
<div id="publish-history"></div>
</aside>
<div class="unit-location">
<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 @@
<% } %>
</h3>
<!--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>-->
<div class="wrapper-last-draft bar-mod-content">
<p class="copy meta">
<% if (has_changes && edited_on && edited_by) {
var message = gettext("Draft saved on %(last_saved_date)s by %(edit_username)s") %>
<%= interpolate(message, {
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-->
<!--<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