← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~pappacena/launchpad:comment-editing-ui-bugcomment into launchpad:master

 

Thiago F. Pappacena has proposed merging ~pappacena/launchpad:comment-editing-ui-bugcomment into launchpad:master with ~pappacena/launchpad:comment-editing-ui as a prerequisite.

Commit message:
Adding editing option to bug comments

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/402604
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~pappacena/launchpad:comment-editing-ui-bugcomment into launchpad:master.
diff --git a/lib/lp/answers/stories/question-workflow.txt b/lib/lp/answers/stories/question-workflow.txt
index 7d23e23..5e39acd 100755
--- a/lib/lp/answers/stories/question-workflow.txt
+++ b/lib/lp/answers/stories/question-workflow.txt
@@ -219,7 +219,7 @@ The confirmed answer is also highlighted.
     <img ... src="/@@/favourite-yes" ... title="Marked as best answer"/>
 
     >>> print(soup.find(
-    ...     'div', 'boardCommentBody highlighted editable-message-body'
+    ...     'div', 'boardCommentBody highlighted editable-message-text'
     ... ).decode_contents())
     <p>New version of the firefox package are available with SVG support
     enabled. You can use apt-get or adept to upgrade.</p>
@@ -290,8 +290,8 @@ answerer back to None.
     >>> bestAnswer.find('strong') is None
     True
 
-    >>> bestAnswer.find('div', 'boardCommentBody editable-message-body')
-    <div class="boardCommentBody editable-message-body"
+    >>> bestAnswer.find('div', 'boardCommentBody editable-message-text')
+    <div class="boardCommentBody editable-message-text"
     itemprop="commentText"><p>New version of the firefox package
     are available with SVG support enabled. You can use apt-get or adept to
     upgrade.</p></div>
@@ -357,9 +357,9 @@ The answer's message is also highlighted as the best answer.
     No Privileges Person (no-priv)
 
     >>> message = soup.find(
-    ...     'div', 'boardCommentBody highlighted editable-message-body')
+    ...     'div', 'boardCommentBody highlighted editable-message-text')
     >>> print(message)
-    <div class="boardCommentBody highlighted editable-message-body"
+    <div class="boardCommentBody highlighted editable-message-text"
     itemprop="commentText"><p>New version of the firefox package are
     available with SVG support enabled. You can use apt-get or adept to
     upgrade.</p></div>
diff --git a/lib/lp/answers/templates/questionmessage-display.pt b/lib/lp/answers/templates/questionmessage-display.pt
index c4cc488..2a5be75 100644
--- a/lib/lp/answers/templates/questionmessage-display.pt
+++ b/lib/lp/answers/templates/questionmessage-display.pt
@@ -27,13 +27,13 @@
       tal:attributes="title context/datecreated/fmt:datetime;
         datetime context/datecreated/fmt:isodate"
       tal:content="context/datecreated/fmt:displaydate">Thursday
-    13:21</time>
+    13:21</time><span tal:condition="not:context/date_last_edited">:</span>
     <span tal:condition="context/date_last_edited">
         (last edit <time
               itemprop="editTime"
               tal:attributes="title context/date_last_edited/fmt:datetime;
                 datetime context/date_last_edited/fmt:isodate"
-              tal:content="context/date_last_edited/fmt:displaydate" />)
+              tal:content="context/date_last_edited/fmt:displaydate" />):
       </span>
     </td>
     <td>
@@ -47,12 +47,14 @@
   </tr></tbody></table>
   </div>
 
-  <div class="boardCommentBody"
-    tal:attributes="class python: view.getBodyCSSClass() + ' editable-message-body'"
-    itemprop="commentText"
-    tal:content="structure
-      context/text_contents/fmt:obfuscate-email/fmt:email-to-html">
-    Message text.
+  <div class="editable-message-body">
+    <div class="boardCommentBody"
+      tal:attributes="class python: view.getBodyCSSClass() + ' editable-message-text'"
+      itemprop="commentText"
+      tal:content="structure
+        context/text_contents/fmt:obfuscate-email/fmt:email-to-html">
+      Message text.
+    </div>
   </div>
 
   <div class="editable-message-form" style="display: none">
diff --git a/lib/lp/bugs/browser/bugcomment.py b/lib/lp/bugs/browser/bugcomment.py
index 2302d83..2d1822e 100644
--- a/lib/lp/bugs/browser/bugcomment.py
+++ b/lib/lp/bugs/browser/bugcomment.py
@@ -52,6 +52,7 @@ from lp.services.webapp import (
     Navigation,
     stepthrough,
     )
+from lp.services.webapp.authorization import check_permission
 from lp.services.webapp.breadcrumb import Breadcrumb
 from lp.services.webapp.interfaces import ILaunchBag
 
@@ -350,12 +351,20 @@ class BugCommentBoxView(LaunchpadView, BugCommentBoxViewMixin):
 
     expand_reply_box = False
 
+    @property
+    def can_edit(self):
+        return check_permission('launchpad.Edit', self.context)
+
 
 class BugCommentBoxExpandedReplyView(LaunchpadView, BugCommentBoxViewMixin):
     """Render a comment box with reply field expanded."""
 
     expand_reply_box = True
 
+    @property
+    def can_edit(self):
+        return False
+
 
 @adapter(IBugComment, IWebServiceClientRequest)
 @implementer(Interface)
diff --git a/lib/lp/bugs/stories/bugattachments/xx-delete-bug-attachment.txt b/lib/lp/bugs/stories/bugattachments/xx-delete-bug-attachment.txt
index f705c8a..b9f7292 100644
--- a/lib/lp/bugs/stories/bugattachments/xx-delete-bug-attachment.txt
+++ b/lib/lp/bugs/stories/bugattachments/xx-delete-bug-attachment.txt
@@ -24,11 +24,17 @@ The attachment is now visible on the bug page.
 There will also be a comment with a link to the attachment in its body.
 
     >>> print_comments(user_browser.contents)
-    <p>This would be a real killer feature...</p>
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>This would be a real killer
+       feature...</p></div>
     ----------------------------------------
-    <p>Oddly enough the bug system seems only capable...</p>
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>Oddly enough the bug system seems
+       only capable...</p></div>
     ----------------------------------------
     Attachment: Great deal
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"></div>
     <BLANKLINE>
     ----------------------------------------
 
@@ -80,9 +86,13 @@ Since the attachment has been deleted, the comment referencing it will no
 longer be visible.
 
     >>> print_comments(user_browser.contents)
-    <p>This would be a real killer feature...</p>
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>This would be a real
+       killer feature...</p></div>
     ----------------------------------------
-    <p>Oddly enough the bug system seems only capable...</p>
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>Oddly enough the bug system
+       seems only capable...</p></div>
     ----------------------------------------
 
 XXX Abel Deuring, 2009-11-25: We should check here that attempts to
diff --git a/lib/lp/bugs/stories/bugs/xx-add-comment-bugtask-edit.txt b/lib/lp/bugs/stories/bugs/xx-add-comment-bugtask-edit.txt
index cb230ec..d2e6dcb 100644
--- a/lib/lp/bugs/stories/bugs/xx-add-comment-bugtask-edit.txt
+++ b/lib/lp/bugs/stories/bugs/xx-add-comment-bugtask-edit.txt
@@ -21,4 +21,4 @@ The user was returned to the bug page, and the comment was added.
     >>> main_content = find_main_content(user_browser.contents)
     >>> last_comment = main_content('div', 'boardCommentBody')[-1]
     >>> print(last_comment.div.decode_contents())
-    <p>A comment with no change to the bug task.</p>
+    <div...><p>A comment with no change to the bug task.</p></div>
diff --git a/lib/lp/bugs/stories/bugs/xx-add-comment-distribution-no-current-release.txt b/lib/lp/bugs/stories/bugs/xx-add-comment-distribution-no-current-release.txt
index f28a028..b90a49f 100644
--- a/lib/lp/bugs/stories/bugs/xx-add-comment-distribution-no-current-release.txt
+++ b/lib/lp/bugs/stories/bugs/xx-add-comment-distribution-no-current-release.txt
@@ -17,4 +17,4 @@ it's still possible to add comments to the bug.
     >>> for comment_div in find_tags_by_class(
     ...     user_browser.contents, 'boardCommentBody'):
     ...     print(comment_div.div.decode_contents())
-    <p>A new comment.</p>
+    <div...><p>A new comment.</p></div>
diff --git a/lib/lp/bugs/stories/bugs/xx-bug-activity.txt b/lib/lp/bugs/stories/bugs/xx-bug-activity.txt
index d2e3dc1..95d0d4f 100644
--- a/lib/lp/bugs/stories/bugs/xx-bug-activity.txt
+++ b/lib/lp/bugs/stories/bugs/xx-bug-activity.txt
@@ -222,12 +222,16 @@ bundled with that comment in the UI.
     >>> admin_browser.getControl('Importance').value = ['Low']
     >>> admin_browser.getControl('Comment').value = "Lookit, a change!"
     >>> admin_browser.getControl("Save Changes").click()
+
+Note that "Lookit, a change!" appears twice: once displaying the message
+itself, and once again inside the textarea to edit the message.
     >>> print_comments(admin_browser.contents)
     Foo Bar (name16)
     wrote
     ... ago:
     #2
     Lookit, a change!
+    Lookit, a change!
     Changed in mozilla-firefox (Ubuntu):
     status:
     New → Confirmed
diff --git a/lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt b/lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt
index 0bc014c..1bef19e 100644
--- a/lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt
+++ b/lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt
@@ -30,25 +30,41 @@ truncated.
     ...     comment_divs = soup('div', 'boardCommentBody')
     ...     for div_tag in comment_divs:
     ...         print(div_tag)
-    >>> print_comments(browser.contents) #doctest: -ELLIPSIS
+    >>> print_comments(browser.contents) #doctest: +ELLIPSIS
     <div class="boardCommentBody">
-    <a href="http://bugs.launchpad.test/tomcat/+bug/2/comments/1/+download";>Download
+    <a href="http://bugs...test/tomcat/+bug/2/comments/1/+download";>Download
     full text</a> (363 bytes)
-    <div class="comment-text" itemprop="commentText"><p>This
+      <div class="editable-message-body">
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>This
     would be a real killer feature. If there...</p></div>
     <p>
     <a href="/tomcat/+bug/2/comments/1">Read more...</a>
     </p>
     </div>
+    <div class="editable-message-form" style="display: none">
+    <textarea rows="10" style="width: 100%">This would be a real...</textarea>
+    <input class="editable-message-update-btn" type="button" value="Update"/>
+    <input class="editable-message-cancel-btn" type="button" value="Cancel"/>
+    </div>
+    </div>
     <div class="boardCommentBody">
-    <a href="http://bugs.launchpad.test/tomcat/+bug/2/comments/2/+download";>Download
+    <a href="http://bugs...test/tomcat/+bug/2/comments/2/+download";>Download
     full text</a> (364 bytes)
-    <div class="comment-text" itemprop="commentText"><p>Oddly
-    enough the bug system seems only capabl...</p></div>
+      <div class="editable-message-body">
+    <div class="comment-text editable-message-text"
+          itemprop="commentText"><p>Oddly enough the bug system seems only
+      capabl...</p></div>
     <p>
     <a href="/tomcat/+bug/2/comments/2">Read more...</a>
     </p>
     </div>
+    <div class="editable-message-form" style="display: none">
+    <textarea rows="10" style="width: 100%">Oddly enough the bug...</textarea>
+    <input class="editable-message-update-btn" type="button" value="Update"/>
+    <input class="editable-message-cancel-btn" type="button" value="Cancel"/>
+    </div>
+    </div>
 
 Let's click on the first "Read more..." link.
 
@@ -61,15 +77,22 @@ The whole comment is visible on this page:
     >>> print(browser.title)
     Comment #1 : Bug #2 (blackhole) : Bugs : Tomcat
 
-    >>> print_comments(browser.contents) #doctest: -ELLIPSIS
+    >>> print_comments(browser.contents) #doctest: +ELLIPSIS
     <div class="boardCommentBody">
-    <div class="comment-text" itemprop="commentText"><p>This
-      would be a real killer feature. If there is already code
+    <div class="editable-message-body">
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>This would be a real killer feature.
+      If there is already code
       to make it possible, why aren't there tons of press announcements
       about the secuirty possibilities. Imagine - no more embarrassing
-      emails for Mr Gates... everything they delete would actually
-      disappear! I'm sure Redmond will switch over as soon as they hear
-      about this. It's not a bug, it's a feature!</p></div>
+      emails for ... disappear! I'm sure Redmond will switch over as soon as
+      they hear about this. It's not a bug, it's a feature!</p></div>
+    </div>
+    <div class="editable-message-form" style="display: none">
+    <textarea rows="10" style="width: 100%">This would be a...</textarea>
+    <input class="editable-message-update-btn" type="button" value="Update"/>
+    <input class="editable-message-cancel-btn" type="button" value="Cancel"/>
+    </div>
     </div>
 
     >>> config_data  = config.pop('max_comment_data')
diff --git a/lib/lp/bugs/stories/bugs/xx-bug-create-question.txt b/lib/lp/bugs/stories/bugs/xx-bug-create-question.txt
index 35d576e..ed2fd5d 100644
--- a/lib/lp/bugs/stories/bugs/xx-bug-create-question.txt
+++ b/lib/lp/bugs/stories/bugs/xx-bug-create-question.txt
@@ -84,7 +84,7 @@ bugtask directly.
 They see their comment was appended to the bug report's messages.
 
     >>> print(extract_text(
-    ...     find_tags_by_class(str(content), 'boardCommentBody')[-1]))
+    ...     find_tags_by_class(str(content), 'editable-message-text')[-1]))
     This bug is a question.
 
 No Privileges Person looks at the page heading and sees that Foo Bar is
diff --git a/lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt b/lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt
index 91435b0..e92f1ef 100644
--- a/lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt
+++ b/lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt
@@ -78,7 +78,7 @@ Admin users will see the hidden message highlighted with an
 'adminHiddenComment' style.
 
     >>> print(' '.join(last_comment.parent['class']))
-    boardComment adminHiddenComment
+    boardComment editable-message adminHiddenComment
 
 Admin users can also reach the message via direct link, and it is
 highlighted with the 'adminHiddenComment style there too.
@@ -95,7 +95,7 @@ highlighted with the 'adminHiddenComment style there too.
     >>> last_comment = main_content('div', 'boardCommentBody')[-1]
     >>> last_comment_text = extract_text(last_comment.div)
     >>> print(' '.join(last_comment.parent['class']))
-    boardComment adminHiddenComment
+    boardComment editable-message adminHiddenComment
 
 Also for the owner of comment the message is still visible in the bug page.
 
@@ -112,7 +112,7 @@ Owner of the comment will see the hidden message highlighted with an
 'adminHiddenComment' style.
 
     >>> print(' '.join(last_comment.parent['class']))
-    boardComment adminHiddenComment
+    boardComment editable-message adminHiddenComment
 
 Owner of the comment can also reach the message via direct link, and it is
 highlighted with the 'adminHiddenComment style there too.
@@ -129,4 +129,4 @@ highlighted with the 'adminHiddenComment style there too.
     >>> last_comment = main_content('div', 'boardCommentBody')[-1]
     >>> last_comment_text = extract_text(last_comment.div)
     >>> print(' '.join(last_comment.parent['class']))
-    boardComment adminHiddenComment
+    boardComment editable-message adminHiddenComment
diff --git a/lib/lp/bugs/stories/bugwatches/xx-bugwatch-comments.txt b/lib/lp/bugs/stories/bugwatches/xx-bugwatch-comments.txt
index b1e9221..576043d 100644
--- a/lib/lp/bugs/stories/bugwatches/xx-bugwatch-comments.txt
+++ b/lib/lp/bugs/stories/bugwatches/xx-bugwatch-comments.txt
@@ -7,19 +7,25 @@ These comments can be displayed like any other comments on a bug. Bug
 
     >>> user_browser.open('http://launchpad.test/bugs/15')
     >>> print_comments(user_browser.contents)
-    <p>Package: gnome-volume...manager...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>Package: gnome-volume...manager...
     ----------------------------------------
-    <p>reassign 308994 pmount...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>reassign 308994 pmount...
     ----------------------------------------
-    <p>reassign 308994 gnome-volume-...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>reassign 308994 gnome-volume-...
     ----------------------------------------
-    <p>reassign 308994 pmount...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>reassign 308994 pmount...
     ----------------------------------------
-    <p>Hi!...Usually CD-ROMs are handled in /etc/fstab, so this might
-    not even be a...pmount bug...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>Hi!...Usually CD-ROMs are
+       handled in /etc/fstab, so this might not even be a...pmount bug...
     ----------------------------------------
-    <p>I'll be happy to add the info you request to the bug report
-    if it will...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>I'll be happy to add the info you request to
+      the bug report if it will...
     ----------------------------------------
 
 The comments imported for a watch can be seen on that watch's +comments
@@ -32,17 +38,23 @@ page. This page isn't linked to, so we need to browse to it directly.
 The ordinary user can't see these comments:
 
     >>> print_comments(user_browser.contents)
-    <p>Package: gnome-volume...manager...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>Package: gnome-volume...manager...
     ----------------------------------------
-    <p>reassign 308994 pmount...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>reassign 308994 pmount...
     ----------------------------------------
-    <p>reassign 308994 gnome-volume-...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>reassign 308994 gnome-volume-...
     ----------------------------------------
-    <p>reassign 308994 pmount...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>reassign 308994 pmount...
     ----------------------------------------
-    <p>Hi!...Usually CD-ROMs are handled in /etc/fstab, so this might
-    not even be a...pmount bug...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>Hi!...Usually CD-ROMs are handled
+       in /etc/fstab, so this might not even be a...pmount bug...
     ----------------------------------------
-    <p>I'll be happy to add the info you request to the bug report
-    if it will...
+    <div class="comment-text editable-message-text"
+         itemprop="commentText"><p>I'll be happy to add the info you request to
+       the bug report if it will...
     ----------------------------------------
diff --git a/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-tools.txt b/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-tools.txt
index ba8dda6..e9629f2 100644
--- a/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-tools.txt
+++ b/lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-tools.txt
@@ -142,12 +142,13 @@ And three comments were added, including the empty comment that was
 created for the attachments.
 
     >>> print_comments(user_browser.contents)
-    <p>This should be added as a comment.</p>
+    <div...><p>This should be added as a comment.</p></div>
     ----------------------------------------
-    <p>This should be added as another comment.</p>
+    <div...><p>This should be added as another comment.</p></div>
     ----------------------------------------
     Attachment: attachment1
     Attachment: Attachment description.
+    <div class="comment-text editable-message-text"...></div>
     ----------------------------------------
 
 
diff --git a/lib/lp/bugs/templates/bugcomment-box.pt b/lib/lp/bugs/templates/bugcomment-box.pt
index 1b087d7..2380d00 100644
--- a/lib/lp/bugs/templates/bugcomment-box.pt
+++ b/lib/lp/bugs/templates/bugcomment-box.pt
@@ -9,8 +9,9 @@
               python: comment.bugwatch and 'remoteBugComment' or '';
               admin_comment_hidden_class
               python: comment.show_for_admin and 'adminHiddenComment' or ''"
-  tal:attributes="class string:boardComment ${remote_bug_comment_class}
-                 ${admin_comment_hidden_class}">
+  tal:attributes="class string:boardComment editable-message
+                 ${remote_bug_comment_class} ${admin_comment_hidden_class};
+                 data-baseurl comment/fmt:url">
 
   <div class="boardCommentDetails">
     <table>
@@ -26,7 +27,14 @@
                 datetime comment/datecreated/fmt:isodate"
               tal:content="comment/datecreated/fmt:displaydate">
                 7 minutes ago
-            </time>:
+            </time><span tal:condition="not:comment/date_last_edited">:</span>
+            <span tal:condition="comment/date_last_edited">
+              (last edit <time
+                    itemprop="editTime"
+                    tal:attributes="title comment/date_last_edited/fmt:datetime;
+                      datetime comment/date_last_edited/fmt:isodate"
+                    tal:content="comment/date_last_edited/fmt:displaydate" />):
+            </span>
               <a tal:attributes="href comment/fmt:url"
                  tal:condition="comment/display_title">
                 <strong tal:content="comment/title" />
@@ -47,13 +55,26 @@
                 datetime comment/datecreated/fmt:isodate"
               tal:content="comment/datecreated/fmt:displaydate">
               7 minutes ago
-              </time>:
+              </time><span tal:condition="not:comment/date_last_edited">:</span>
+              <span tal:condition="comment/date_last_edited">
+                (last edit
+                <time itemprop="editTime"
+                      tal:attributes="
+                        title comment/date_last_edited/fmt:datetime;
+                        datetime comment/date_last_edited/fmt:isodate"
+                      tal:content="comment/date_last_edited/fmt:displaydate" />):
+              </span>
               <a tal:attributes="href comment/fmt:url">
                 <strong tal:condition="comment/display_title"
                         tal:content="comment/title" />
               </a>
           </td>
 
+          <td>
+            <img class="sprite edit action-icon editable-message-edit-btn"
+                 tal:condition="view/can_edit"/>
+          </td>
+
           <td class="bug-comment-index">
           <a itemprop="url"
              tal:attributes="href comment/fmt:url"
diff --git a/lib/lp/bugs/templates/bugtask-index.pt b/lib/lp/bugs/templates/bugtask-index.pt
index 2e4fb91..8517916 100644
--- a/lib/lp/bugs/templates/bugtask-index.pt
+++ b/lib/lp/bugs/templates/bugtask-index.pt
@@ -12,7 +12,7 @@
       <script type="text/javascript">
         LPJS.use('base', 'node', 'oop', 'event', 'lp.bugs.bugtask_index',
                   'lp.bugs.subscribers', 'lp.code.branchmergeproposal.diff',
-                  'lp.app.comment', function(Y) {
+                  'lp.app.comment', 'lp.services.messages.edit', function(Y) {
             Y.on('domready', function() {
                 Y.lp.code.branchmergeproposal.diff.connect_diff_links();
                 Y.lp.bugs.bugtask_index.setup_bugtask_index();
@@ -26,6 +26,8 @@
                         '/+bug-portlet-subscribers-details',
                     subscribe_someone_else_link: '.menu-link-addsubscriber'
                 }, window);
+
+                Y.lp.services.messages.edit.setup();
             });
          });
       </script>
diff --git a/lib/lp/services/comments/templates/comment-body.pt b/lib/lp/services/comments/templates/comment-body.pt
index d68be76..cce285b 100644
--- a/lib/lp/services/comments/templates/comment-body.pt
+++ b/lib/lp/services/comments/templates/comment-body.pt
@@ -5,11 +5,22 @@
 
   <a tal:replace="structure view/download_link"
      tal:condition="context/too_long">Download full text</a>
-  <div class="comment-text" itemprop="commentText" tal:content="structure
-      context/text_for_display/fmt:obfuscate-email/fmt:email-to-html" />
-  <tal:renderable condition="not: context/too_long_to_render">
-  <p tal:condition="context/too_long">
-    <a tal:attributes="href context/fmt:url">Read more...</a>
-  </p>
-  </tal:renderable >
+  <div class="editable-message-body">
+    <div class="comment-text editable-message-text" itemprop="commentText"
+         tal:content="structure
+         context/text_for_display/fmt:obfuscate-email/fmt:email-to-html" />
+    <tal:renderable condition="not: context/too_long_to_render">
+    <p tal:condition="context/too_long">
+      <a tal:attributes="href context/fmt:url">Read more...</a>
+    </p>
+    </tal:renderable >
+  </div>
+
+  <div class="editable-message-form" style="display: none"
+       tal:condition="python: not getattr(context, 'hide_text', False)">
+     <textarea style="width: 100%" rows="10"
+               tal:content="context/text_contents" />
+     <input type="button" value="Update" class="editable-message-update-btn" />
+     <input type="button" value="Cancel" class="editable-message-cancel-btn" />
+  </div>
 </tal:root>
diff --git a/lib/lp/services/messages/javascript/messages.edit.js b/lib/lp/services/messages/javascript/messages.edit.js
index 096525f..f61eb87 100644
--- a/lib/lp/services/messages/javascript/messages.edit.js
+++ b/lib/lp/services/messages/javascript/messages.edit.js
@@ -111,6 +111,7 @@ YUI.add('lp.services.messages.edit', function(Y) {
             var node = container.getDOMNode();
             var baseurl = node.dataset.baseurl;
             var msg_body = container.one('.editable-message-body');
+            var msg_body_text = container.one('.editable-message-text');
             var msg_form = container.one('.editable-message-form');
             var edit_btn = container.one('.editable-message-edit-btn');
             var update_btn = msg_form.one('.editable-message-update-btn');
@@ -145,7 +146,7 @@ YUI.add('lp.services.messages.edit', function(Y) {
                         // When finished updating at the backend, re-enable UI
                         // elements and display the new message.
                         var html_msg = module.htmlify_msg(new_content);
-                        msg_body.getDOMNode().innerHTML = html_msg;
+                        msg_body_text.getDOMNode().innerHTML = html_msg;
                         module.hide_edit_message_field(msg_body, msg_form);
                         textarea.disabled = false;
                         update_btn.getDOMNode().disabled = false;
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 0fd6056..ebba572 100644
--- a/lib/lp/services/messages/javascript/tests/test_messages.edit.html
+++ b/lib/lp/services/messages/javascript/tests/test_messages.edit.html
@@ -54,8 +54,11 @@ GNU Affero General Public License version 3 (see the file LICENSE).
 
         <div class="editable-message" id="first-message"
              data-baseurl="/message/1">
-            <div class="editable-message-body"></div>
-            <img class="sprite edit action-icon editable-message-edit-btn">
+            <div class="editable-message-body">
+                <div class="editable-message-text"></div>
+                The message is above :)
+            </div>
+            <img class="sprite edit action-icon editable-message-edit-btn" />
 
             <div class="editable-message-form">
                 <textarea></textarea>
@@ -66,8 +69,11 @@ GNU Affero General Public License version 3 (see the file LICENSE).
 
         <div class="editable-message" id="second-message"
              data-baseurl="/message/2">
-            <div class="editable-message-body"></div>
-            <img class="sprite edit action-icon editable-message-edit-btn">
+            <div class="editable-message-body">
+                <div class="editable-message-text"></div>
+                The message is above :)
+            </div>
+            <img class="sprite edit action-icon editable-message-edit-btn" />
 
             <div class="editable-message-form">
                 <textarea></textarea>
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 9f9f549..edb5bb4 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,10 @@ YUI.add('lp.services.messages.edit.test', function(Y) {
                 this.containers[0].one(".editable-message-body"),
                 this.containers[1].one(".editable-message-body")
             ];
+            this.msg_body_texts = [
+                this.containers[0].one(".editable-message-text"),
+                this.containers[1].one(".editable-message-text")
+            ];
             this.msg_forms = [
                 this.containers[0].one(".editable-message-form"),
                 this.containers[1].one(".editable-message-form")
@@ -57,7 +61,7 @@ YUI.add('lp.services.messages.edit.test', function(Y) {
             ];
 
             for(var i=0 ; i<this.containers.length ; i++) {
-                this.msg_bodies[i].getDOMNode().innerHTML = (
+                this.msg_body_texts[i].getDOMNode().innerHTML = (
                     "Message number " + i);
                 this.msg_bodies[i].setStyle('display', '');
                 this.msg_forms[i].setStyle('display', '');
@@ -121,7 +125,7 @@ YUI.add('lp.services.messages.edit.test', function(Y) {
             });
             Y.Assert.areSame(
                 '<p>edited<br>message &lt;foo&gt;</p>',
-                this.msg_bodies[1].getDOMNode().innerHTML);
+                this.msg_body_texts[1].getDOMNode().innerHTML);
 
             // All forms should be released.
             Y.Assert.isFalse(this.textareas[1].getDOMNode().disabled);

Follow ups