Merge ~pappacena/launchpad:comment-editing-ui-list-revisions into launchpad:master

Proposed by Thiago F. Pappacena
Status: Merged
Approved by: Thiago F. Pappacena
Approved revision: 9e068e5c903b1409bc54fb6c58f3b88e7b8ecb97
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~pappacena/launchpad:comment-editing-ui-list-revisions
Merge into: launchpad:master
Diff against target: 540 lines (+318/-27)
8 files modified
lib/canonical/launchpad/icing/css/base.scss (+55/-0)
lib/lp/answers/browser/question.py (+1/-3)
lib/lp/answers/stories/question-workflow.txt (+1/-1)
lib/lp/answers/templates/questionmessage-display.pt (+22/-2)
lib/lp/services/messages/interfaces/messagerevision.py (+2/-1)
lib/lp/services/messages/javascript/messages.edit.js (+103/-18)
lib/lp/services/messages/javascript/tests/test_messages.edit.html (+58/-1)
lib/lp/services/messages/javascript/tests/test_messages.edit.js (+76/-1)
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+403213@code.launchpad.net

Commit message

Showing message revision list in the UI

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
review: Approve
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Pushed the requested changes. This should be good to go now.

Revision history for this message
Colin Watson (cjwatson) :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lib/canonical/launchpad/icing/css/base.scss b/lib/canonical/launchpad/icing/css/base.scss
index 6ee2779..1e33ca7 100644
--- a/lib/canonical/launchpad/icing/css/base.scss
+++ b/lib/canonical/launchpad/icing/css/base.scss
@@ -579,6 +579,61 @@ body {
579 margin: 5px;579 margin: 5px;
580 }580 }
581 }581 }
582
583 .message-revision-container {
584 position: absolute;
585 background-color: white;
586 margin-top: 20px;
587 display: none;
588 border: 1px solid #ddd;
589 width: 45em;
590 z-index: 100;
591 max-height: 200px;
592 overflow-y: auto;
593 overflow-x: hidden;
594
595 .message-revision-container-header {
596 background-color: #eee;
597 border-bottom: 1px solid #ddd;
598 padding: 10px;
599
600 span {
601 text-align: left;
602 display: inline-block;
603 font-size: 110%;
604 font-weight: bold;
605 }
606
607 img {
608 float: right;
609 cursor: pointer;
610 }
611 }
612
613 .message-revision-item {
614 border-bottom: 1px solid #ddd;
615 padding: 2px;
616
617 .message-revision-title {
618 padding: 5px;
619 cursor: pointer;
620 font-weight: 300;
621 }
622
623 .message-revision-body {
624 display: none;
625 padding-left: 20px;
626 padding-bottom: 10px;
627 }
628 }
629
630 .active {
631 background-color: #eee;
632 .message-revision-title {
633 font-weight: bold;
634 }
635 }
636 }
582 }637 }
583638
584@import 'typography',639@import 'typography',
diff --git a/lib/lp/answers/browser/question.py b/lib/lp/answers/browser/question.py
index 9d4986d..52cff40 100644
--- a/lib/lp/answers/browser/question.py
+++ b/lib/lp/answers/browser/question.py
@@ -1195,13 +1195,11 @@ class QuestionMessageDisplayView(LaunchpadView):
1195 return check_permission('launchpad.Moderate', self.context)1195 return check_permission('launchpad.Moderate', self.context)
11961196
1197 def getBoardCommentCSSClass(self):1197 def getBoardCommentCSSClass(self):
1198 css_classes = ["boardComment"]1198 css_classes = ["boardComment", "editable-message"]
1199 if not self.context.visible:1199 if not self.context.visible:
1200 # If a comment that isn't visible is being rendered, it's being1200 # If a comment that isn't visible is being rendered, it's being
1201 # rendered for an admin or registry_expert.1201 # rendered for an admin or registry_expert.
1202 css_classes.append("adminHiddenComment")1202 css_classes.append("adminHiddenComment")
1203 if self.can_edit:
1204 css_classes.append("editable-message")
1205 return " ".join(css_classes)1203 return " ".join(css_classes)
12061204
1207 @property1205 @property
diff --git a/lib/lp/answers/stories/question-workflow.txt b/lib/lp/answers/stories/question-workflow.txt
index 5e39acd..1a0b67a 100755
--- a/lib/lp/answers/stories/question-workflow.txt
+++ b/lib/lp/answers/stories/question-workflow.txt
@@ -215,7 +215,7 @@ The confirmed answer is also highlighted.
215215
216 >>> soup = find_main_content(owner_browser.contents)216 >>> soup = find_main_content(owner_browser.contents)
217 >>> bestAnswer = soup.find_all('div', 'boardComment')[-2]217 >>> bestAnswer = soup.find_all('div', 'boardComment')[-2]
218 >>> print(bestAnswer.find('img'))218 >>> print(bestAnswer.find_all('img')[1])
219 <img ... src="/@@/favourite-yes" ... title="Marked as best answer"/>219 <img ... src="/@@/favourite-yes" ... title="Marked as best answer"/>
220220
221 >>> print(soup.find(221 >>> print(soup.find(
diff --git a/lib/lp/answers/templates/questionmessage-display.pt b/lib/lp/answers/templates/questionmessage-display.pt
index fc3651c..c1ed29a 100644
--- a/lib/lp/answers/templates/questionmessage-display.pt
+++ b/lib/lp/answers/templates/questionmessage-display.pt
@@ -14,6 +14,25 @@
14 <tbody>14 <tbody>
15 <tr>15 <tr>
16 <td>16 <td>
17 <div class="message-revision-container">
18 <div class="message-revision-container-header">
19 <span>Revision history for this message</span>
20 <img src="/+icing/build/overlay/assets/skins/sam/images/close.gif"
21 class="message-revision-close"/>
22 </div>
23 <script type="text/template">
24 <div class='message-revision-item'>
25 <div class='message-revision-title'>
26 <a class="js-action">
27 Revision #{revision}, created at {date_created}
28 </a>
29 </div>
30 <div class='message-revision-body'>{content}</div>
31 </div>
32 </script>
33
34 <div class="message-revision-list"></div>
35 </div>
17 <tal:bestanswer condition="view/isBestAnswer">36 <tal:bestanswer condition="view/isBestAnswer">
18 <img src="/@@/favourite-yes" style="float:right;" alt="Best"37 <img src="/@@/favourite-yes" style="float:right;" alt="Best"
19 title="Marked as best answer" />38 title="Marked as best answer" />
@@ -28,11 +47,12 @@
28 datetime context/datecreated/fmt:isodate"47 datetime context/datecreated/fmt:isodate"
29 tal:content="context/datecreated/fmt:displaydate">Thursday 13:2148 tal:content="context/datecreated/fmt:displaydate">Thursday 13:21
30 </time><span class="editable-message-last-edit-date"><tal:last-edit condition="context/date_last_edited">49 </time><span class="editable-message-last-edit-date"><tal:last-edit condition="context/date_last_edited">
31 (last edit <time50 <a href="#" class="editable-message-last-edit-link"
51 tal:condition="context/date_last_edited">(last edit <time
32 itemprop="editTime"52 itemprop="editTime"
33 tal:attributes="title context/date_last_edited/fmt:datetime;53 tal:attributes="title context/date_last_edited/fmt:datetime;
34 datetime context/date_last_edited/fmt:isodate"54 datetime context/date_last_edited/fmt:isodate"
35 tal:content="context/date_last_edited/fmt:displaydate" />)</tal:last-edit>:55 tal:content="context/date_last_edited/fmt:displaydate" />)</a></tal:last-edit>:
36 </span>56 </span>
37 </td>57 </td>
38 <td>58 <td>
diff --git a/lib/lp/services/messages/interfaces/messagerevision.py b/lib/lp/services/messages/interfaces/messagerevision.py
index 3ee5a90..aa0ff0a 100644
--- a/lib/lp/services/messages/interfaces/messagerevision.py
+++ b/lib/lp/services/messages/interfaces/messagerevision.py
@@ -35,7 +35,8 @@ class IMessageRevisionView(Interface):
35 """IMessageRevision readable attributes."""35 """IMessageRevision readable attributes."""
36 id = Int(title=_("ID"), required=True, readonly=True)36 id = Int(title=_("ID"), required=True, readonly=True)
3737
38 revision = Int(title=_("Revision number"), required=True, readonly=True)38 revision = exported(
39 Int(title=_("Revision number"), required=True, readonly=True))
3940
40 content = exported(Text(41 content = exported(Text(
41 title=_("The message at the given revision"),42 title=_("The message at the given revision"),
diff --git a/lib/lp/services/messages/javascript/messages.edit.js b/lib/lp/services/messages/javascript/messages.edit.js
index a1e6806..f84bf72 100644
--- a/lib/lp/services/messages/javascript/messages.edit.js
+++ b/lib/lp/services/messages/javascript/messages.edit.js
@@ -2,7 +2,8 @@
2 * GNU Affero General Public License version 3 (see the file LICENSE).2 * GNU Affero General Public License version 3 (see the file LICENSE).
3 *3 *
4 * This modules controls HTML comments in order to make them editable. To do4 * This modules controls HTML comments in order to make them editable. To do
5 * so, it requires:5 * so, it requires some definitions (see test_messages.edit.html file for the
6 * complete structure reference):
6 * - A div container with the class .editable-message containing everything7 * - A div container with the class .editable-message containing everything
7 * else related to the message8 * else related to the message
8 * - A data-baseurl="/path/to/msg" on the .editable-message container9 * - A data-baseurl="/path/to/msg" on the .editable-message container
@@ -14,6 +15,16 @@
14 * - A .editable-message-last-edit-date span, where we update the date of the15 * - A .editable-message-last-edit-date span, where we update the date of the
15 * last message editing.16 * last message editing.
16 *17 *
18 * For the message revision history, you should define:
19 * - A .editable-message-last-edit-link, that will show the revisions pop-up
20 * once clicked.
21 * - A .message-revision-container, holding the header and the body of the
22 * revision list, and the template for each revision item.
23 * - A .message-revision-container-header.
24 * - A .message-revision-list, where the revisions will be placed.
25 * - A <script type="text/template">, with the definition of how each item
26 * should look like.
27 *
17 * Once those HTML elements are available in the page, this module should be28 * Once those HTML elements are available in the page, this module should be
18 * initialized with `lp.services.messages.edit.setup()`.29 * initialized with `lp.services.messages.edit.setup()`.
19 *30 *
@@ -23,15 +34,6 @@
23YUI.add('lp.services.messages.edit', function(Y) {34YUI.add('lp.services.messages.edit', function(Y) {
24 var module = Y.namespace('lp.services.messages.edit');35 var module = Y.namespace('lp.services.messages.edit');
2536
26 // XXX pappacena 2021-05-21: We should drop this message once we have a
27 // way to list the old message revisions in the web UI.
28 module.msg_edit_success_notification = (
29 "Message edited, but the original content may still be publicly " +
30 "visible using the API.<br />Please " +
31 "<a href='https://launchpad.net/+apidoc/devel.html#message'>" +
32 "check the API documentation</a> in case you " +
33 "need to remove old message revisions."
34 );
35 module.msg_edit_error_notification = (37 module.msg_edit_error_notification = (
36 "There was an error updating the comment. " +38 "There was an error updating the comment. " +
37 "Please try again in a few minutes."39 "Please try again in a few minutes."
@@ -115,7 +117,7 @@ YUI.add('lp.services.messages.edit', function(Y) {
115 // text area.117 // text area.
116 module.showEditMessageField(elements.msg_body, elements.msg_form);118 module.showEditMessageField(elements.msg_body, elements.msg_form);
117 elements.msg_form.one('textarea').getDOMNode().focus();119 elements.msg_form.one('textarea').getDOMNode().focus();
118 }120 };
119121
120 // What to do when a user clicks "cancel edit" button.122 // What to do when a user clicks "cancel edit" button.
121 module.onEditCancelClick = function(elements) {123 module.onEditCancelClick = function(elements) {
@@ -134,13 +136,15 @@ YUI.add('lp.services.messages.edit', function(Y) {
134136
135 module.saveMessageContent(137 module.saveMessageContent(
136 baseurl, new_content,138 baseurl, new_content,
137 function(err) { module.onMessageSaved(elements, new_content); },139 function(err) {
140 module.onMessageSaved(elements, new_content, baseurl);
141 },
138 function(err) { module.onMessageSaveError(elements, err); }142 function(err) { module.onMessageSaveError(elements, err); }
139 );143 );
140 };144 };
141145
142 // What to do when a message is saved in the backend.146 // What to do when a message is saved in the backend.
143 module.onMessageSaved = function(elements, new_content) {147 module.onMessageSaved = function(elements, new_content, baseurl) {
144 // When finished updating at the backend, re-enable UI148 // When finished updating at the backend, re-enable UI
145 // elements and display the new message.149 // elements and display the new message.
146 var html_msg = module.htmlify_msg(new_content);150 var html_msg = module.htmlify_msg(new_content);
@@ -150,11 +154,18 @@ YUI.add('lp.services.messages.edit', function(Y) {
150 elements.textarea.getDOMNode().disabled = false;154 elements.textarea.getDOMNode().disabled = false;
151 elements.update_btn.getDOMNode().disabled = false;155 elements.update_btn.getDOMNode().disabled = false;
152 module.hideLoading(elements.container);156 module.hideLoading(elements.container);
153 module.showNotification(
154 elements.container,
155 module.msg_edit_success_notification, true);
156 elements.last_edit.getDOMNode().innerHTML = (157 elements.last_edit.getDOMNode().innerHTML = (
157 ' (last edit a moment ago): ');158 '<a href="#" class="editable-message-last-edit-link">' +
159 '(last edit a moment ago):' +
160 '</a>');
161
162 // Wire click handler to the newly created "last edit" button.
163 var last_edit_btn = elements.container.one(
164 '.editable-message-last-edit-link');
165 last_edit_btn.on('click', function(e) {
166 e.preventDefault();
167 module.onLastEditClick(elements, baseurl);
168 });
158 };169 };
159170
160 // What to do when a message fails to update on the backend.171 // What to do when a message fails to update on the backend.
@@ -168,6 +179,72 @@ YUI.add('lp.services.messages.edit', function(Y) {
168 elements.update_btn.getDOMNode().disabled = false;179 elements.update_btn.getDOMNode().disabled = false;
169 };180 };
170181
182 module.fillMessageRevisions = function(elements, revisions) {
183 // Position the message revision list element.
184 revisions = revisions.reverse();
185 var revisions_container = elements.container.one(
186 ".message-revision-container");
187 var last_edit_el = elements.last_edit.getDOMNode();
188 var target_position = last_edit_el.getBoundingClientRect();
189 var nodes_holder = revisions_container.one(".message-revision-list");
190 var template = revisions_container.one(
191 "script[type='text/template']").getDOMNode().innerHTML;
192
193 revisions_container.setStyle('left', target_position.left);
194 revisions_container.setStyle('display', 'block');
195 revisions_container.one(".message-revision-close").on(
196 "click", function() {
197 nodes_holder.getDOMNode().innerHTML = '';
198 revisions_container.setStyle('display', 'none');
199 });
200
201 var content = "";
202 revisions.forEach(function(rev) {
203 var attrs = rev.getAttrs();
204 var date_created = new Date(attrs.date_created);
205 attrs.date_created = date_created.toLocaleString();
206 attrs.content = module.htmlify_msg(attrs.content);
207 content += Y.Lang.sub(template, attrs);
208 });
209
210 nodes_holder.getDOMNode().innerHTML = content;
211 nodes_holder.all(".message-revision-item").each(function(rev_item) {
212 rev_item.one(".message-revision-title").on('click', function() {
213 nodes_holder.all('.message-revision-body').setStyle(
214 'display', 'none');
215 var body = rev_item.one('.message-revision-body');
216 var current_display = body.getStyle('display');
217 body.setStyle(
218 'display', current_display === 'block'? 'none' : 'block');
219 nodes_holder.all(".message-revision-item").removeClass(
220 'active');
221 rev_item.addClass('active');
222 });
223 });
224 };
225
226 module.onLastEditClick = function(elements, baseurl) {
227 // Hide all open revision containers.
228 Y.all('.message-revision-container').each(function(container) {
229 container.setStyle('display', 'none');
230 });
231
232 var url = "/api/devel" + baseurl + "/revisions";
233 var config = {
234 on: {
235 success: function(response) {
236 module.fillMessageRevisions(elements, response.entries);
237 },
238 failure: function(err) {
239 alert("Error fetching revisions.");
240 }
241 },
242 // XXX pappacena 2021-05-19: Pagination will be needed here.
243 size: 100
244 };
245 this.lp_client.get(url, config);
246 };
247
171 module.wireEventHandlers = function(container) {248 module.wireEventHandlers = function(container) {
172 var node = container.getDOMNode();249 var node = container.getDOMNode();
173 var baseurl = node.dataset.baseurl;250 var baseurl = node.dataset.baseurl;
@@ -179,7 +256,8 @@ YUI.add('lp.services.messages.edit', function(Y) {
179 "edit_btn": container.one('.editable-message-edit-btn'),256 "edit_btn": container.one('.editable-message-edit-btn'),
180 "update_btn": container.one('.editable-message-update-btn'),257 "update_btn": container.one('.editable-message-update-btn'),
181 "cancel_btn": container.one('.editable-message-cancel-btn'),258 "cancel_btn": container.one('.editable-message-cancel-btn'),
182 "last_edit": container.one('.editable-message-last-edit-date')259 "last_edit": container.one('.editable-message-last-edit-date'),
260 "last_edit_btn": container.one('.editable-message-last-edit-link')
183 };261 };
184 // If the msg body or the msg form are not defined, don't try to do262 // If the msg body or the msg form are not defined, don't try to do
185 // anything else.263 // anything else.
@@ -190,6 +268,13 @@ YUI.add('lp.services.messages.edit', function(Y) {
190268
191 module.hideEditMessageField(elements.msg_body, elements.msg_form);269 module.hideEditMessageField(elements.msg_body, elements.msg_form);
192270
271 if (elements.last_edit_btn) {
272 elements.last_edit_btn.on('click', function(e) {
273 e.preventDefault();
274 module.onLastEditClick(elements, baseurl);
275 });
276 }
277
193 // If the edit button is not present, do not try to bind the278 // If the edit button is not present, do not try to bind the
194 // handlers.279 // handlers.
195 if (!elements.edit_btn || !baseurl) {280 if (!elements.edit_btn || !baseurl) {
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 3036d88..e6a27c2 100644
--- a/lib/lp/services/messages/javascript/tests/test_messages.edit.html
+++ b/lib/lp/services/messages/javascript/tests/test_messages.edit.html
@@ -52,10 +52,45 @@ GNU Affero General Public License version 3 (see the file LICENSE).
52 <li>lp.services.messages.edit.test</li>52 <li>lp.services.messages.edit.test</li>
53 </ul>53 </ul>
5454
55 <!-- First editable message -->
55 <div class="editable-message" id="first-message"56 <div class="editable-message" id="first-message"
56 data-baseurl="/message/1">57 data-baseurl="/message/1">
58 <!-- Revision list container and its template -->
59 <div class="message-revision-container">
60 <!-- The revision list pop-up header, with the image that closes
61 the pop-up when clicked. -->
62 <div class="message-revision-container-header">
63 <span>Revision history for this message</span>
64 <img src="/+icing/build/overlay/assets/skins/sam/images/close.gif"
65 class="message-revision-close"/>
66 </div>
67 <!-- The template for each revision item in the list. The
68 content of this tag will be repeated multiple times, replacing
69 the {variable} with each MessageRevision entry returned by
70 the API.
71 -->
72 <script type="text/template">
73 <div class='message-revision-item'>
74 <!-- The description of the revision, that will expand the
75 revision content once clicked. -->
76 <div class='message-revision-title'>
77 <a class="js-action">Revision #{revision}, created at {date_created}</a>
78 </div>
79 <!-- The revision content itself -->
80 <div class='message-revision-body'>{content}</div>
81 </div>
82 </script>
83 <!-- This is the place where all the revisions will be placed,
84 by applying the above template to each MessageRevision entry
85 returned by the API.
86 -->
87 <div class="message-revision-list"></div>
88 </div>
89
90 <!-- Message body -->
57 <div>91 <div>
58 Comment from @some-user a while ago92 Comment from @some-user a while ago
93 Comment from @some-user a while ago
59 <span class="editable-message-last-edit-date">:</span>94 <span class="editable-message-last-edit-date">:</span>
60 </div>95 </div>
61 <div class="editable-message-body">96 <div class="editable-message-body">
@@ -71,12 +106,34 @@ GNU Affero General Public License version 3 (see the file LICENSE).
71 </div>106 </div>
72 </div>107 </div>
73108
109 <!-- Second editable message -->
74 <div class="editable-message" id="second-message"110 <div class="editable-message" id="second-message"
75 data-baseurl="/message/2">111 data-baseurl="/message/2">
112 <!-- Revision list container and its template -->
113 <div class="message-revision-container">
114 <div class="message-revision-container-header">
115 <span>Revision history for this message</span>
116 <img src="/+icing/build/overlay/assets/skins/sam/images/close.gif"
117 class="message-revision-close"/>
118 </div>
119 <script type="text/template">
120 <div class='message-revision-item'>
121 <div class='message-revision-title'>
122 <a class="js-action">Revision #{revision}, created at {date_created}</a>
123 </div>
124 <div class='message-revision-body'>{content}</div>
125 </div>
126 </script>
127 <div class="message-revision-list"></div>
128 </div>
129
130 <!-- Message body -->
76 <div>131 <div>
77 Comment from @some-user a while ago132 Comment from @some-user a while ago
78 <span class="editable-message-last-edit-date">133 <span class="editable-message-last-edit-date">
79 (last edit 5 minutes ago):134 <a href="#" class="editable-message-last-edit-link">
135 (last edit 5 minutes ago):
136 </a>
80 </span>137 </span>
81 </div>138 </div>
82 <div class="editable-message-body">139 <div class="editable-message-body">
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 a8a982c..5d12dab 100644
--- a/lib/lp/services/messages/javascript/tests/test_messages.edit.js
+++ b/lib/lp/services/messages/javascript/tests/test_messages.edit.js
@@ -35,6 +35,14 @@ YUI.add('lp.services.messages.edit.test', function(Y) {
35 this.containers[0].one(".editable-message-last-edit-date"),35 this.containers[0].one(".editable-message-last-edit-date"),
36 this.containers[1].one(".editable-message-last-edit-date")36 this.containers[1].one(".editable-message-last-edit-date")
37 ];37 ];
38 this.revision_history_link = [
39 this.containers[0].one(".editable-message-last-edit-link"),
40 this.containers[1].one(".editable-message-last-edit-link")
41 ];
42 this.revision_history_lists = [
43 this.containers[0].one(".message-revision-list"),
44 this.containers[1].one(".message-revision-list")
45 ];
38 this.msg_bodies = [46 this.msg_bodies = [
39 this.containers[0].one(".editable-message-body"),47 this.containers[0].one(".editable-message-body"),
40 this.containers[1].one(".editable-message-body")48 this.containers[1].one(".editable-message-body")
@@ -73,6 +81,7 @@ YUI.add('lp.services.messages.edit.test', function(Y) {
73 this.last_edit[0].getDOMNode().innerHTML = ':';81 this.last_edit[0].getDOMNode().innerHTML = ':';
74 this.last_edit[1].getDOMNode().innerHTML = (82 this.last_edit[1].getDOMNode().innerHTML = (
75 '(last edit 5 minutes ago):');83 '(last edit 5 minutes ago):');
84 this.revision_history_lists[i].getDOMNode().innerHTML = '';
76 }85 }
77 },86 },
7887
@@ -160,8 +169,74 @@ YUI.add('lp.services.messages.edit.test', function(Y) {
160 // Check that the "last edit" header changed.169 // Check that the "last edit" header changed.
161 Y.Assert.areSame(":", this.last_edit[0].getDOMNode().innerHTML);170 Y.Assert.areSame(":", this.last_edit[0].getDOMNode().innerHTML);
162 Y.Assert.areSame(171 Y.Assert.areSame(
163 " (last edit a moment ago): ",172 '<a href="#" class="editable-message-last-edit-link">' +
173 '(last edit a moment ago):</a>',
164 this.last_edit[1].getDOMNode().innerHTML);174 this.last_edit[1].getDOMNode().innerHTML);
175 },
176
177 test_shows_revision_history: function() {
178 module.setup();
179 module.lp_client.io_provider = new Y.lp.testing.mockio.MockIo();
180 var revisions_container = this.containers[1].one(
181 '.message-revision-container');
182 // Revisions container should not be shown before it's clicked.
183 Y.Assert.areSame('none', revisions_container.getStyle('display'));
184
185 // Simulates the click and the request.
186 this.revision_history_link[1].simulate('click');
187
188 var response = {
189 "total_size": 1, "start": 0,
190 "entries": [{
191 "revision": 1,
192 "content": "content 1",
193 "date_created": "2021-05-10T19:41:36.102749+00:00"
194 }, {
195 "revision": 2,
196 "content": "content 2",
197 "date_created": "2021-05-11T22:17:11.000123+00:00"
198 }]
199 };
200 module.lp_client.io_provider.success({
201 responseText: Y.JSON.stringify(response),
202 responseHeaders: {'Content-Type': 'application/json'}
203 });
204
205 // Make sure it didn't fill the first container.
206 Y.Assert.areSame(
207 "", this.revision_history_lists[0].getDOMNode().innerHTML);
208
209 // Check that revision list pop-up is shown
210 Y.Assert.areSame('block', revisions_container.getStyle('display'));
211
212 // Check the items in the pop-up revisions list.
213 var revisions = this.revision_history_lists[1].all(
214 ".message-revision-item");
215 Y.Assert.areSame(2, revisions.size());
216 revisions.each(function(rev, i) {
217 // Entries are shown in reverse order.
218 var entry = response.entries[response.entries.length - i -1];
219 var date_created = new Date(entry.date_created);
220 entry['formatted_date'] = date_created.toLocaleString();
221 var title = rev.one('.message-revision-title');
222 var body = rev.one('.message-revision-body');
223 var expected_title = Y.Lang.sub(
224 '<a class="js-action">' +
225 'Revision #{revision}, created at {formatted_date}' +
226 '</a>',
227 entry);
228 Y.Assert.areSame(
229 expected_title, title.getDOMNode().innerHTML.trim());
230 Y.Assert.areSame(
231 module.htmlify_msg(entry.content),
232 body.getDOMNode().innerHTML);
233 });
234
235 // Lets make sure that a click on the "close" button hides the
236 // revisions list.
237 revisions_container.one(
238 '.message-revision-close').simulate('click');
239 Y.Assert.areSame('none', revisions_container.getStyle('display'));
165 }240 }
166241
167 };242 };