launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #27218
[Merge] ~cjwatson/launchpad:message-revisions-time-rendering into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:message-revisions-time-rendering into launchpad:master.
Commit message:
Render message revision timestamps in webapp
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1933079 in Launchpad itself: "answers.launchpad.net timestamp of changes of comment shown in wrong time zone"
https://bugs.launchpad.net/launchpad/+bug/1933079
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/404485
This causes them to be displayed according to the user's configured time zone.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:message-revisions-time-rendering into launchpad:master.
diff --git a/lib/lp/answers/templates/questionmessage-display.pt b/lib/lp/answers/templates/questionmessage-display.pt
index c1ed29a..49973ab 100644
--- a/lib/lp/answers/templates/questionmessage-display.pt
+++ b/lib/lp/answers/templates/questionmessage-display.pt
@@ -24,7 +24,7 @@
<div class='message-revision-item'>
<div class='message-revision-title'>
<a class="js-action">
- Revision #{revision}, created at {date_created}
+ Revision #{revision}, created at {date_created_display}
</a>
</div>
<div class='message-revision-body'>{content}</div>
diff --git a/lib/lp/bugs/templates/bugcomment-box.pt b/lib/lp/bugs/templates/bugcomment-box.pt
index 34e5789..1e1882a 100644
--- a/lib/lp/bugs/templates/bugcomment-box.pt
+++ b/lib/lp/bugs/templates/bugcomment-box.pt
@@ -24,7 +24,7 @@
<div class='message-revision-item'>
<div class='message-revision-title'>
<a class="js-action">
- Revision #{revision}, created at {date_created}
+ Revision #{revision}, created at {date_created_display}
</a>
</div>
<div class='message-revision-body'>{content}</div>
diff --git a/lib/lp/code/templates/codereviewcomment-header.pt b/lib/lp/code/templates/codereviewcomment-header.pt
index 3d2b976..3511b9f 100644
--- a/lib/lp/code/templates/codereviewcomment-header.pt
+++ b/lib/lp/code/templates/codereviewcomment-header.pt
@@ -13,7 +13,7 @@
<div class='message-revision-item'>
<div class='message-revision-title'>
<a class="js-action">
- Revision #{revision}, created at {date_created}
+ Revision #{revision}, created at {date_created_display}
</a>
</div>
<div class='message-revision-body'>{content}</div>
diff --git a/lib/lp/services/messages/interfaces/messagerevision.py b/lib/lp/services/messages/interfaces/messagerevision.py
index aa0ff0a..43f0c9a 100644
--- a/lib/lp/services/messages/interfaces/messagerevision.py
+++ b/lib/lp/services/messages/interfaces/messagerevision.py
@@ -25,6 +25,7 @@ from zope.schema import (
Datetime,
Int,
Text,
+ TextLine,
)
from lp import _
@@ -55,6 +56,12 @@ class IMessageRevisionView(Interface):
title=_("The time when this message revision was created."),
required=True, readonly=True))
+ date_created_display = exported(TextLine(
+ title=_(
+ "The time when this message revision was created, rendered in the "
+ "user's timezone for the web UI."),
+ required=True, readonly=True))
+
date_deleted = exported(Datetime(
title=_("The time when this message revision was created."),
required=False, readonly=True))
diff --git a/lib/lp/services/messages/javascript/messages.edit.js b/lib/lp/services/messages/javascript/messages.edit.js
index c6e79b6..56762e8 100644
--- a/lib/lp/services/messages/javascript/messages.edit.js
+++ b/lib/lp/services/messages/javascript/messages.edit.js
@@ -201,8 +201,6 @@ YUI.add('lp.services.messages.edit', function(Y) {
var content = "";
revisions.forEach(function(rev) {
var attrs = rev.getAttrs();
- var date_created = new Date(attrs.date_created);
- attrs.date_created = date_created.toLocaleString();
attrs.content = module.htmlify_msg(attrs.content);
content += Y.Lang.sub(template, attrs);
});
diff --git a/lib/lp/services/messages/javascript/tests/test_messages.edit.html b/lib/lp/services/messages/javascript/tests/test_messages.edit.html
index e6a27c2..9d394c2 100644
--- a/lib/lp/services/messages/javascript/tests/test_messages.edit.html
+++ b/lib/lp/services/messages/javascript/tests/test_messages.edit.html
@@ -74,7 +74,7 @@ GNU Affero General Public License version 3 (see the file LICENSE).
<!-- The description of the revision, that will expand the
revision content once clicked. -->
<div class='message-revision-title'>
- <a class="js-action">Revision #{revision}, created at {date_created}</a>
+ <a class="js-action">Revision #{revision}, created at {date_created_display}</a>
</div>
<!-- The revision content itself -->
<div class='message-revision-body'>{content}</div>
@@ -119,7 +119,7 @@ GNU Affero General Public License version 3 (see the file LICENSE).
<script type="text/template">
<div class='message-revision-item'>
<div class='message-revision-title'>
- <a class="js-action">Revision #{revision}, created at {date_created}</a>
+ <a class="js-action">Revision #{revision}, created at {date_created_display}</a>
</div>
<div class='message-revision-body'>{content}</div>
</div>
diff --git a/lib/lp/services/messages/javascript/tests/test_messages.edit.js b/lib/lp/services/messages/javascript/tests/test_messages.edit.js
index f5cbd39..d9644f0 100644
--- a/lib/lp/services/messages/javascript/tests/test_messages.edit.js
+++ b/lib/lp/services/messages/javascript/tests/test_messages.edit.js
@@ -190,11 +190,11 @@ YUI.add('lp.services.messages.edit.test', function(Y) {
"entries": [{
"revision": 1,
"content": "content 1",
- "date_created": "2021-05-10T19:41:36.102749+00:00"
+ "date_created_display": "2021-05-10 19:41:36 UTC"
}, {
"revision": 2,
"content": "content 2",
- "date_created": "2021-05-11T22:17:11.000123+00:00"
+ "date_created_display": "2021-05-11 22:17:11 UTC"
}]
};
module.lp_client.io_provider.success({
@@ -216,13 +216,11 @@ YUI.add('lp.services.messages.edit.test', function(Y) {
revisions.each(function(rev, i) {
// Entries are shown in reverse order.
var entry = response.entries[response.entries.length - i -1];
- var date_created = new Date(entry.date_created);
- entry['formatted_date'] = date_created.toLocaleString();
var title = rev.one('.message-revision-title');
var body = rev.one('.message-revision-body');
var expected_title = Y.Lang.sub(
'<a class="js-action">' +
- 'Revision #{revision}, created at {formatted_date}' +
+ 'Revision #{revision}, created at {date_created_display}' +
'</a>',
entry);
Y.Assert.areSame(
diff --git a/lib/lp/services/messages/model/messagerevision.py b/lib/lp/services/messages/model/messagerevision.py
index 535ff66..5dc20e3 100644
--- a/lib/lp/services/messages/model/messagerevision.py
+++ b/lib/lp/services/messages/model/messagerevision.py
@@ -20,6 +20,7 @@ from storm.locals import (
)
from zope.interface import implementer
+from lp.app.browser.tales import DateTimeFormatterAPI
from lp.services.database.constants import UTC_NOW
from lp.services.database.interfaces import IStore
from lp.services.database.stormbase import StormBase
@@ -87,6 +88,10 @@ class MessageRevision(StormBase):
def content(self):
return '\n\n'.join(i.content for i in self.chunks)
+ @property
+ def date_created_display(self):
+ return DateTimeFormatterAPI(self.date_created).datetime()
+
def deleteContent(self):
store = IStore(self)
store.find(MessageRevisionChunk, message_revision=self).remove()
diff --git a/lib/lp/services/messages/tests/test_messagerevision.py b/lib/lp/services/messages/tests/test_messagerevision.py
index 80d1a14..19cc931 100644
--- a/lib/lp/services/messages/tests/test_messagerevision.py
+++ b/lib/lp/services/messages/tests/test_messagerevision.py
@@ -14,6 +14,7 @@ from testtools.matchers import (
from zope.security.interfaces import Unauthorized
from zope.security.proxy import ProxyFactory
+from lp.app.browser.tales import DateTimeFormatterAPI
from lp.bugs.interfaces.bugmessage import IBugMessage
from lp.services.database.interfaces import IStore
from lp.services.database.sqlbase import get_transaction_timestamp
@@ -85,6 +86,7 @@ class TestMessageRevisionAPI(MessageTypeScenariosMixin, TestCaseWithFactory):
msg = self.makeMessage(content="initial content")
msg.editContent("new content 1")
msg.editContent("final content")
+ dates_created = [revision.date_created for revision in msg.revisions]
ws = self.getWebservice(self.person)
url = self.getMessageAPIURL(msg)
ws_message = ws.get(url).jsonBody()
@@ -95,37 +97,45 @@ class TestMessageRevisionAPI(MessageTypeScenariosMixin, TestCaseWithFactory):
"total_size": Equals(2)}))
self.assertThat(revisions["entries"], MatchesListwise([
ContainsDict({
- "date_created": Not(Is(None)),
- "date_deleted": Is(None),
"content": Equals("initial content"),
+ "date_created": Equals(dates_created[0].isoformat()),
+ "date_created_display": Equals(
+ DateTimeFormatterAPI(dates_created[0]).datetime()),
+ "date_deleted": Is(None),
"self_link": EndsWith("/revisions/1")
- }),
+ }),
ContainsDict({
- "date_created": Not(Is(None)),
- "date_deleted": Is(None),
"content": Equals("new content 1"),
+ "date_created": Equals(dates_created[1].isoformat()),
+ "date_created_display": Equals(
+ DateTimeFormatterAPI(dates_created[1]).datetime()),
+ "date_deleted": Is(None),
"self_link": EndsWith("/revisions/2")
- })]))
+ })]))
def test_get_single_revision(self):
msg = self.makeMessage(content="initial content")
msg.editContent("new content 1")
+ date_created = msg.revisions[0].date_created
ws = self.getWebservice(self.person)
with person_logged_in(self.person):
revision_url = api_url(msg.revisions[0])
revision = ws.get(revision_url).jsonBody()
self.assertThat(revision, ContainsDict({
- "date_created": Not(Is(None)),
- "date_deleted": Is(None),
- "content": Equals("initial content"),
- "self_link": EndsWith("/revisions/1")
+ "content": Equals("initial content"),
+ "date_created": Equals(date_created.isoformat()),
+ "date_created_display": Equals(
+ DateTimeFormatterAPI(date_created).datetime()),
+ "date_deleted": Is(None),
+ "self_link": EndsWith("/revisions/1")
}))
def test_delete_revision_content(self):
msg = self.makeMessage(content="initial content")
msg.editContent("new content 1")
msg.editContent("final content")
+ dates_created = [revision.date_created for revision in msg.revisions]
with person_logged_in(self.person):
revision_url = api_url(msg.revisions[0])
@@ -136,16 +146,19 @@ class TestMessageRevisionAPI(MessageTypeScenariosMixin, TestCaseWithFactory):
revision = ws.get(revision_url).jsonBody()
self.assertThat(revision, ContainsDict({
- "date_created": Not(Is(None)),
- "date_deleted": Not(Is(None)),
"content": Equals(""),
+ "date_created": Equals(dates_created[0].isoformat()),
+ "date_created_display": Equals(
+ DateTimeFormatterAPI(dates_created[0]).datetime()),
+ "date_deleted": Not(Is(None)),
"self_link": EndsWith("/revisions/1")
- }))
+ }))
def test_delete_revision_content_denied_for_non_owners(self):
msg = self.makeMessage(content="initial content")
msg.editContent("new content 1")
msg.editContent("final content")
+ dates_created = [revision.date_created for revision in msg.revisions]
someone_else = self.factory.makePerson()
with person_logged_in(self.person):
@@ -157,9 +170,10 @@ class TestMessageRevisionAPI(MessageTypeScenariosMixin, TestCaseWithFactory):
revision = ws.get(revision_url).jsonBody()
self.assertThat(revision, ContainsDict({
- "date_created": Not(Is(None)),
- "date_deleted": Is(None),
"content": Equals("initial content"),
+ "date_created": Equals(dates_created[0].isoformat()),
+ "date_created_display": Equals(
+ DateTimeFormatterAPI(dates_created[0]).datetime()),
+ "date_deleted": Is(None),
"self_link": EndsWith("/revisions/1")
- }))
-
+ }))