← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~ilasc/launchpad:add-delete-comment-revision-ui into launchpad:master

 

Ioana Lasc has proposed merging ~ilasc/launchpad:add-delete-comment-revision-ui into launchpad:master.

Commit message:
Add delete comment revision capability

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~ilasc/launchpad/+git/launchpad/+merge/406151
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~ilasc/launchpad:add-delete-comment-revision-ui into launchpad:master.
diff --git a/lib/canonical/launchpad/icing/css/base.scss b/lib/canonical/launchpad/icing/css/base.scss
index 1e33ca7..086e64d 100644
--- a/lib/canonical/launchpad/icing/css/base.scss
+++ b/lib/canonical/launchpad/icing/css/base.scss
@@ -625,6 +625,13 @@ body {
                 padding-left: 20px;
                 padding-bottom: 10px;
             }
+
+            // If the content was deleted, we show a default message with
+            // this CSS class.
+            .deleted-content {
+                padding: 5px;
+                opacity: 50%;
+            }
         }
 
         .active {
diff --git a/lib/lp/answers/templates/questionmessage-display.pt b/lib/lp/answers/templates/questionmessage-display.pt
index 49973ab..f9014a9 100644
--- a/lib/lp/answers/templates/questionmessage-display.pt
+++ b/lib/lp/answers/templates/questionmessage-display.pt
@@ -8,7 +8,8 @@
   tal:define="css_classes view/getBoardCommentCSSClass"
   tal:attributes="class string:${css_classes};
                   id string:comment-${context/index};
-                  data-baseurl context/fmt:url">
+                  data-baseurl context/fmt:url;
+                  data-i-can-edit view/can_edit">
   <div class="boardCommentDetails">
     <table>
       <tbody>
@@ -23,6 +24,9 @@
         <script type="text/template">
           <div class='message-revision-item'>
             <div class='message-revision-title'>
+                <a class="sprite remove action-icon message-revision-del-btn">
+                    Remove
+                </a>
                 <a class="js-action">
                     Revision #{revision}, created at {date_created_display}
                 </a>
diff --git a/lib/lp/services/messages/javascript/messages.edit.js b/lib/lp/services/messages/javascript/messages.edit.js
index 56762e8..1da3dbd 100644
--- a/lib/lp/services/messages/javascript/messages.edit.js
+++ b/lib/lp/services/messages/javascript/messages.edit.js
@@ -7,6 +7,7 @@
  *  - A div container with the class .editable-message containing everything
  *      else related to the message
  *  - A data-baseurl="/path/to/msg" on the .editable-message container
+ *  - A data-i-can-edit="True|False" on the .editable-message container
  *  - A .editable-message-body container with the original msg content
  *  - A .editable-message-edit-btn element inside the main container, that will
  *      switch the view to edit form when clicked.
@@ -39,6 +40,20 @@ YUI.add('lp.services.messages.edit', function(Y) {
         "Please try again in a few minutes."
     );
 
+    module.confirm_delete_revision_msg = (
+        "Are you sure you want to delete this revision content?");
+
+    module.deleted_content_msg = (
+        "<span class='deleted-content'>" +
+        "  Content deleted by the user." +
+        "</span>"
+    );
+
+    // Making it easier to mock on tests.
+    module.confirm = function(msg) {
+        return confirm(msg);
+    };
+
     module.htmlify_msg = function(text) {
         text = text.replace(/&/g, "&amp;");
         text = text.replace(/</g, "&lt;");
@@ -182,6 +197,7 @@ YUI.add('lp.services.messages.edit', function(Y) {
     module.fillMessageRevisions = function(elements, revisions) {
         // Position the message revision list element.
         revisions = revisions.reverse();
+        var i_can_edit = elements.container.getData('i-can-edit') === "True";
         var revisions_container = elements.container.one(
             ".message-revision-container");
         var last_edit_el = elements.last_edit.getDOMNode();
@@ -198,14 +214,26 @@ YUI.add('lp.services.messages.edit', function(Y) {
                 revisions_container.setStyle('display', 'none');
             });
 
-        var content = "";
+        nodes_holder.getDOMNode().innerHTML = "";
         revisions.forEach(function(rev) {
             var attrs = rev.getAttrs();
-            attrs.content = module.htmlify_msg(attrs.content);
-            content += Y.Lang.sub(template, attrs);
+            if (!attrs.date_deleted) {
+                attrs.content = module.htmlify_msg(attrs.content);
+            }
+            else {
+                attrs.content = module.deleted_content_msg;
+            }
+            var node = Y.DOM.create(Y.Lang.sub(template, attrs));
+            node.dataset['revision_url'] = attrs.self_link;
+            nodes_holder.appendChild(node);
+
+            if(attrs.date_deleted || !i_can_edit) {
+                // If it was already deleted or I don't have permission to
+                // delete it, remove the "delete button".
+                module.removeDeleteRevisionButton(Y.Node(node));
+            }
         });
 
-        nodes_holder.getDOMNode().innerHTML = content;
         nodes_holder.all(".message-revision-item").each(function(rev_item) {
             rev_item.one(".message-revision-title").on('click', function() {
                 nodes_holder.all('.message-revision-body').setStyle(
@@ -218,9 +246,44 @@ YUI.add('lp.services.messages.edit', function(Y) {
                     'active');
                 rev_item.addClass('active');
             });
+
+            var delete_btn = rev_item.one(".message-revision-del-btn");
+            if (delete_btn) {
+                delete_btn.on('click', function() {
+                    module.deleteMessageRevisionContent(rev_item);
+                });
+            }
         });
     };
 
+    module.removeDeleteRevisionButton = function(rev_item_node) {
+        var delete_btn = rev_item_node.one('.message-revision-del-btn');
+        if (delete_btn) {
+            var node_to_remove = delete_btn.getDOMNode();
+            node_to_remove.parentNode.removeChild(node_to_remove);
+        }
+    };
+
+    module.deleteMessageRevisionContent = function(rev_item) {
+        var revision_url = rev_item.getData('revision_url');
+        if (module.confirm(module.confirm_delete_revision_msg)) {
+            var config = {
+                on: {
+                     success: function() {
+                        var body_dom = rev_item.one(
+                            '.message-revision-body').getDOMNode();
+                        body_dom.innerHTML = module.deleted_content_msg;
+                        module.removeDeleteRevisionButton(rev_item);
+                     },
+                     failure: function(err) {
+                        alert("There was an error. Please try again.");
+                     }
+                 }
+            };
+            this.lp_client.named_post(revision_url, 'deleteContent', config);
+        }
+    };
+
     module.onLastEditClick = function(elements, baseurl) {
         // Hide all open revision containers.
         Y.all('.message-revision-container').each(function(container) {
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 9d394c2..c2a38d1 100644
--- a/lib/lp/services/messages/javascript/tests/test_messages.edit.html
+++ b/lib/lp/services/messages/javascript/tests/test_messages.edit.html
@@ -54,7 +54,7 @@ GNU Affero General Public License version 3 (see the file LICENSE).
 
         <!-- First editable message -->
         <div class="editable-message" id="first-message"
-             data-baseurl="/message/1">
+             data-baseurl="/message/1" data-i-can-edit="True">
             <!-- Revision list container and its template -->
             <div class="message-revision-container">
               <!-- The revision list pop-up header, with the image that closes
@@ -74,6 +74,9 @@ 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="sprite remove action-icon message-revision-del-btn">
+                          Remove
+                      </a>
                       <a class="js-action">Revision #{revision}, created at {date_created_display}</a>
                   </div>
                   <!-- The revision content itself -->
@@ -108,7 +111,7 @@ GNU Affero General Public License version 3 (see the file LICENSE).
 
         <!-- Second editable message -->
         <div class="editable-message" id="second-message"
-             data-baseurl="/message/2">
+             data-baseurl="/message/2" data-i-can-edit="True">
             <!-- Revision list container and its template -->
             <div class="message-revision-container">
               <div class="message-revision-container-header">
@@ -119,6 +122,9 @@ 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="sprite remove action-icon message-revision-del-btn">
+                          Remove
+                      </a>
                       <a class="js-action">Revision #{revision}, created at {date_created_display}</a>
                   </div>
                   <div class='message-revision-body'>{content}</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 d9644f0..e3b4d54 100644
--- a/lib/lp/services/messages/javascript/tests/test_messages.edit.js
+++ b/lib/lp/services/messages/javascript/tests/test_messages.edit.js
@@ -78,11 +78,11 @@ YUI.add('lp.services.messages.edit.test', function(Y) {
                 this.msg_bodies[i].setStyle('display', '');
                 this.msg_forms[i].setStyle('display', '');
                 this.textareas[i].getDOMNode().value = '';
-                this.last_edit[0].getDOMNode().innerHTML = ':';
-                this.last_edit[1].getDOMNode().innerHTML = (
-                    '(last edit 5 minutes ago):');
                 this.revision_history_lists[i].getDOMNode().innerHTML = '';
             }
+            this.last_edit[0].getDOMNode().innerHTML = ':';
+            this.last_edit[1].getDOMNode().innerHTML = (
+                '(last edit 5 minutes ago):');
         },
 
         test_instantiation_hides_forms: function() {
@@ -219,24 +219,65 @@ YUI.add('lp.services.messages.edit.test', function(Y) {
                 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 {date_created_display}' +
-                    '</a>',
+                    'Remove  Revision #{revision},'+
+                    ' created at {date_created_display}',
                     entry);
-                Y.Assert.areSame(
-                    expected_title, title.getDOMNode().innerHTML.trim());
+                Y.Assert.areEqual(
+                    expected_title, title.getDOMNode().innerText);
+
                 Y.Assert.areSame(
                     module.htmlify_msg(entry.content),
                     body.getDOMNode().innerHTML);
             });
 
-            // Lets make sure that a click on the "close" button hides the
-            // revisions list.
-            revisions_container.one(
-                '.message-revision-close').simulate('click');
-            Y.Assert.areSame('none', revisions_container.getStyle('display'));
-        }
+            revisions = this.revision_history_lists[1].all(
+                ".message-revision-item");
+            Y.Assert.areSame(2, revisions.size());
 
+            // Delete one revision from the revision list of
+            // the second message
+            revisions.each(function(rev, j) {
+                var entry = response.entries[response.entries.length - j -1];
+                var title = rev.one('.message-revision-title');
+                var body = rev.one('.message-revision-body');
+
+                if (j===0){
+                    // mock user's response to modal widonw that is
+                    // asking the confirmation to delete revision
+                    module.confirm = function(){
+                        return 'True';
+                    };
+                    // user clicks on the Remove icon for the revision
+                    rev.one('.message-revision-del-btn').simulate('click');
+                    module.lp_client.io_provider.success({
+                        responseText: 'null',
+                        responseHeaders: {'Content-Type': 'application/json'}
+                    });
+
+                    // the title displayed for the revision stays the same
+                    var expected_title = Y.Lang.sub(
+                        'Revision #{revision},' +
+                        ' created at {date_created_display}',
+                        entry);
+                    Y.Assert.areSame(
+                        expected_title,
+                        title.getDOMNode().innerText);
+
+                    // the content has changed to reflect deletion
+                    var expected_body = Y.Lang.sub(
+                        'Content deleted by the user.',
+                        entry);
+                    Y.Assert.areEqual(
+                        expected_body, body.getDOMNode().innerText);
+                }
+            });
+            // The number of revisions in the list stays the same
+            // and we asserted above the content displayed has changed
+            // to reflect deletion for revision 2
+            var after_delete_revis = this.revision_history_lists[1].all(
+                ".message-revision-item");
+            Y.Assert.areSame(2, after_delete_revis.size());
+        }
     };
 
     suite.add(new Y.Test.Case(TestMessageEdit));

Follow ups