757e193ec1b1

web: comments, styling, and multiline comments, OH MY
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sun, 13 Jun 2010 04:42:29 -0400
parents ee8d78fbf746
children 7551a383f66a
branches/tags (none)
files review/static/comments.js review/static/style.css review/static/style.less review/templates/changeset.html review/templates/diff.html review/web_ui.py

Changes

--- a/review/static/comments.js	Sun Jun 13 02:45:53 2010 -0400
+++ b/review/static/comments.js	Sun Jun 13 04:42:29 2010 -0400
@@ -1,3 +1,28 @@
+function RenderLineCommentForm(line, currNum) {
+    var comment_form = '\
+            <tr class="comment-form">\
+                <td colspan="3">\
+                    <form id="id_comment-line-form_' + currNum + '" method="POST" action="">\
+                        <span class="lastlinenumber disabled">' + currNum + '</span>\
+                        <div class="field">\
+                            <label class="infield" for="id_comment-line-form_' + currNum + '_body">Comment</label>\
+                            <textarea id="id_comment-line-form_' + currNum + '_body" \
+                                      name="new-comment-body"></textarea>\
+                        </div>\
+                        \
+                        <a class="submit button"><span>Post Comment</span></a>\
+                        <a class="cancel-line button"><span>Cancel</span></a>\
+                        \
+                        <input type="hidden" name="filename" value="<<<FILENAME>>>" />\
+                        <input class="lines" type="hidden" name="lines" value="<<<LINENUMBER>>>" />\
+                    </form>\
+                </td>\
+            </tr>';
+    comment_form = comment_form.replace('<<<FILENAME>>>', line.closest(".file").find(".filename h3 a").html());
+    comment_form = comment_form.replace('<<<LINENUMBER>>>', currNum);
+    return comment_form;
+}
+
 $(function() {
     
     $(".activate a").click(function(event) {
@@ -12,6 +37,12 @@
         return false;
     });
 
+    $("a.cancel-line").live('click', function(event) {
+        $(event.target).closest(".diff").find(".chosen").removeClass("chosen");
+        $(event.target).closest("tr.comment-form").remove();
+        return false;
+    });
+
     $("tr.comment").hover(function(event) {
         var diff = $(event.target).closest(".diff");
         var lines = $(event.target).find(".commentlines").html().split(",");
@@ -21,40 +52,73 @@
     }, function(event) {
         $(".viewing").removeClass("viewing");
     });
-    
-    //$("span.cancel-line a").live("click", function(event) {
-        //$(event.target).closest("tr").prev().removeClass("comment-line-selected").addClass("commentable");
-        //$(event.target).closest("tr").remove();
-        //return false;
-    //});
-    
-    //$("tr.rem.commentable,tr.add.commentable,tr.con.commentable").live("click", function(event) {
-        //$(event.target).closest("tr").addClass("comment-line-selected").removeClass("commentable");
-        //var filename = $(event.target).closest("tr").find(".line-data").children(".filename").first().text();
-        //var linenumber = $(event.target).closest("tr").find(".line-data").children(".linenumber").first().html();
-        
-        //var comment_form = '<tr class="comment-line">\n\
-                //<td>\n\
-                    //<form id="comment-line-form" method="post" action="">\n\
-                        //<div class="field">\n\
-                            //<label for="body">Add a comment on this line:</label>\n\
-                            //<textarea cols="60" rows="6" name="new-comment-body"></textarea>\n\
-                        //</div>\n\
-                        //<div class="buttons">\n\
-                            //<input type="submit" class="button" value="Submit" />\n\
-                            //<span class="cancel-line"><a href="">Cancel</a></span>\n\
-                        //</div>\n\
-                        //<input type="hidden" name="filename" value="<<<FILENAME>>>" />\n\
-                        //<input type="hidden" name="lines" value="<<<LINENUMBER>>>" />\n\
-                    //</form>\n\
-                //</td>\n\
-            //</tr>';
-        //comment_form = comment_form.replace('<<<FILENAME>>>', filename);
-        //comment_form = comment_form.replace('<<<LINENUMBER>>>', linenumber);
-        
-        //$(event.target).closest("tr").after(comment_form);
-        //return false;
-    //});
+
+    var lastSelected = null;
+
+    $(".commentable").click(function(event) {
+        var currNum = parseInt($(this).find(".linenumber").html());
+        var diff = $(this).closest(".diff");
+
+        if ($(this).hasClass("chosen")) {
+            $(this).removeClass("chosen");
+
+            var newLines = "";
+            jQuery.each(diff.find(".chosen .linenumber"), function() {
+                newLines += $(this).html() + ",";
+            });
+            diff.find(".comment-form form .lines").val(newLines);
+
+            lastSelected = null;
+            return false;
+        }
+
+        if (event.shiftKey && lastSelected) {
+            if (lastSelected && jQuery.contains(diff.get(0), lastSelected.get(0))) {
+                var lastNum = parseInt(lastSelected.find(".linenumber").html());
+                if (lastNum > currNum) {
+                    for (i = currNum; i < lastNum; i++) {
+                        diff.find(".line-" + i).addClass("chosen");
+                    }
+                } else {
+                    for (i = currNum; i > lastNum; i--) {
+                        diff.find(".line-" + i).addClass("chosen");
+                    }
+                }
+            }
+        } else {
+            $(this).addClass("chosen");
+        }
+        lastSelected = $(this);
+
+        var lines_chosen = diff.find(".chosen");
+        var last_line = lines_chosen.last();
+        var existing_forms = diff.find(".comment-form");
+
+        if (existing_forms.length) {
+            var existing_form = existing_forms.last();
+            var existing_form_line_number = parseInt(existing_form.find(".lastlinenumber").html());
+            
+            if (existing_form_line_number < currNum) {
+                existing_forms.remove();
+
+                var comment_form = RenderLineCommentForm($(this), currNum);
+                $(this).after(comment_form);
+                diff.find("label").inFieldLabels();
+            }
+
+            var newLines = "";
+            jQuery.each(diff.find(".chosen .linenumber"), function() {
+                newLines += $(this).html() + ",";
+            });
+            diff.find(".comment-form form .lines").val(newLines);
+        } else {
+            var comment_form = RenderLineCommentForm($(this), currNum);
+            $(this).after(comment_form);
+            diff.find("label").inFieldLabels();
+        }
+
+        return false;
+    });
     
     $("label.infield").inFieldLabels();
 });
--- a/review/static/style.css	Sun Jun 13 02:45:53 2010 -0400
+++ b/review/static/style.css	Sun Jun 13 04:42:29 2010 -0400
@@ -11,6 +11,9 @@
 * html .group, *:first-child + html .group {
   zoom: 1;
 }
+html {
+  overflow-y: scroll;
+}
 html, body {
   background-color: #edecc7;
   background: #edecc7 url('bg.png') top left repeat;
@@ -65,6 +68,7 @@
 }
 body .header .remotes form a {
   margin-right: 3px;
+  cursor: pointer;
   font: bold 12px "Helvetica Neue", HelveticaNeue, Arial, Helvetica, sans-serif;
   color: #212000;
   line-height: 1.45;
@@ -243,6 +247,7 @@
   width: 100%;
 }
 #changeset .content .activate a {
+  cursor: pointer;
   font: bold 12px "Helvetica Neue", HelveticaNeue, Arial, Helvetica, sans-serif;
   color: #1e1e1e;
   line-height: 1.45;
@@ -290,6 +295,7 @@
 }
 #changeset .content a.submit {
   margin-right: 4px;
+  cursor: pointer;
   font: bold 12px "Helvetica Neue", HelveticaNeue, Arial, Helvetica, sans-serif;
   color: #1e1e1e;
   line-height: 1.45;
@@ -335,7 +341,8 @@
 #changeset .content a.submit:hover span {
   background-color: #fbfbfb;
 }
-#changeset .content a.cancel {
+#changeset .content a.cancel, #changeset .content a.cancel-line {
+  cursor: pointer;
   font: bold 12px "Helvetica Neue", HelveticaNeue, Arial, Helvetica, sans-serif;
   color: #1e1e1e;
   line-height: 1.45;
@@ -354,16 +361,16 @@
   border-left: 1px solid #a6a6a6;
   border-bottom: 1px solid #959595;
 }
-#changeset .content a.cancel:active {
+#changeset .content a.cancel:active, #changeset .content a.cancel-line:active {
   margin-top: 1px;
   margin-bottom: -1px;
 }
-#changeset .content a.cancel:focus {
+#changeset .content a.cancel:focus, #changeset .content a.cancel-line:focus {
   box-shadow: 0px 0px 3px rgba(100, 100, 200, 0.9);
   -moz-box-shadow: 0px 0px 3px rgba(100, 100, 200, 0.9);
   -webkit-box-shadow: 0px 0px 3px rgba(100, 100, 200, 0.9);
 }
-#changeset .content a.cancel span {
+#changeset .content a.cancel span, #changeset .content a.cancel-line span {
   display: inline-block;
   padding: 0 6px;
   text-shadow: 0px 1px 1px #ffffff;
@@ -371,14 +378,14 @@
   -moz-border-radius: 3px;
   border-radius: 3px;
 }
-#changeset .content a.cancel:hover {
+#changeset .content a.cancel:hover, #changeset .content a.cancel-line:hover {
   border-top: 1px solid #d3d3d3;
   border-right: 1px solid #bbbbbb;
   border-left: 1px solid #bbbbbb;
   border-bottom: 1px solid #a4a4a4;
   background-color: #fbfbfb;
 }
-#changeset .content a.cancel:hover span {
+#changeset .content a.cancel:hover span, #changeset .content a.cancel-line:hover span {
   background-color: #fbfbfb;
 }
 #changeset .content .togglebox form {
@@ -465,10 +472,15 @@
 #changeset .content .file .add-file-comment {
   margin-bottom: 24px;
 }
+#changeset .content .diff {
+  overflow-x: auto;
+  border: 1px solid #ddd;
+  margin-bottom: 24px;
+}
 #changeset .content .diff table {
   width: 100%;
-  border: 1px solid #ddd;
   background-color: #f9f9f9;
+  margin-bottom: 0;
 }
 #changeset .content .diff table td.code:after {
   color: #ccc;
@@ -485,6 +497,24 @@
 #changeset .content .diff table tr.viewing {
   background-color: #f2f2d7;
 }
+#changeset .content .diff table tr.commentable {
+  cursor: pointer;
+}
+#changeset .content .diff table tr.chosen {
+  background-color: #edecc7;
+}
+#changeset .content .diff table tr.comment-form td {
+  line-height: 15px;
+  padding: 10px 10px 15px 56px;
+  border-bottom: 1px solid #ddd;
+  border-top: 1px solid #ddd;
+  background-color: #f4f4f4;
+}
+#changeset .content .diff table tr.comment-form td textarea {
+  width: 500px;
+  height: 50px;
+  border: 1px solid #888888;
+}
 #changeset .content .diff table td {
   border: none;
   line-height: 1;
@@ -511,8 +541,8 @@
 #changeset .content .diff table td.comment {
   line-height: 15px;
   padding: 10px 10px 10px 56px;
-  border-bottom: 1px solid #eee;
-  border-top: 1px solid #eee;
+  border-bottom: 1px solid #ddd;
+  border-top: 1px solid #ddd;
   background-color: #f4f4f4;
 }
 #changeset .content .diff table td.comment .avatar {
--- a/review/static/style.less	Sun Jun 13 02:45:53 2010 -0400
+++ b/review/static/style.less	Sun Jun 13 04:42:29 2010 -0400
@@ -33,6 +33,7 @@
     border-bottom: 1px solid @bottom;
 }
 .button(@bgcolor: #ddd, @fcolor: #000000, @fsize: 14px, @lheight: 1.75) {
+    cursor: pointer;
     font: bold @fsize @font-normal;
     color: @bgcolor - #ccc;
     line-height: @lheight;
@@ -72,6 +73,9 @@
     zoom:1
 }
 
+html {
+    overflow-y: scroll;
+}
 html, body {
     background-color: @c-cream;
     background: @c-cream url('bg.png') top left repeat;
@@ -300,7 +304,7 @@
         &:hover { .button-hover(@c-metal, #000, 12px, 1.45); }
         &:hover span { .button-hover-span(@c-metal, #000, 12px, 1.45); }
     }
-    a.cancel {
+    a.cancel, a.cancel-line {
         .button(@c-metal, #000, 12px, 1.45);
         span { .button-span(@c-metal, #000, 12px, 1.45); }
         &:hover { .button-hover(@c-metal, #000, 12px, 1.45); }
@@ -402,10 +406,14 @@
         }
     }
     .diff {
-        table{
+        overflow-x: auto;
+        border: 1px solid #ddd;
+        margin-bottom: 24px;
+
+        table {
             width: 100%;
-            border: 1px solid #ddd;
             background-color: #f9f9f9;
+            margin-bottom: 0;
 
             td.code:after {
                 color: #ccc;
@@ -423,6 +431,25 @@
                 &.viewing {
                     background-color: lighten(@c-cream, 5%);
                 }
+                &.commentable {
+                    cursor: pointer;
+                }
+                &.chosen {
+                    background-color: @c-cream;
+                }
+                &.comment-form td {
+                    line-height: 15px;
+                    padding: 10px 10px 15px 56px;
+                    border-bottom: 1px solid #ddd;
+                    border-top: 1px solid #ddd;
+                    background-color: #f4f4f4;
+                    
+                    textarea {
+                        width: 500px;
+                        height: 50px;
+                        border: 1px solid @c-light;
+                    }
+                }
             }
 
             td {
@@ -451,8 +478,8 @@
                 &.comment {
                     line-height: 15px;
                     padding: 10px 10px 10px 56px;
-                    border-bottom: 1px solid #eee;
-                    border-top: 1px solid #eee;
+                    border-bottom: 1px solid #ddd;
+                    border-top: 1px solid #ddd;
                     background-color: #f4f4f4;
 
                     .avatar {
--- a/review/templates/changeset.html	Sun Jun 13 02:45:53 2010 -0400
+++ b/review/templates/changeset.html	Sun Jun 13 04:42:29 2010 -0400
@@ -112,7 +112,7 @@
                 <h3><a class="fold" href="#">{{ filename }}</a> <span class="status">&rarr;</span> </h3>
             </div>
 
-            <div class="file-review-contents">
+            <div class="file-review-contents disabled">
                 {% with %}
                     {% set comments = rcset.file_level_comments(filename) %}
 
--- a/review/templates/diff.html	Sun Jun 13 02:45:53 2010 -0400
+++ b/review/templates/diff.html	Sun Jun 13 04:42:29 2010 -0400
@@ -1,3 +1,5 @@
+{% import 'macros.html' as macros %}
+
 <div class="diff">
 
 <table>
--- a/review/web_ui.py	Sun Jun 13 02:45:53 2010 -0400
+++ b/review/web_ui.py	Sun Jun 13 04:42:29 2010 -0400
@@ -94,7 +94,7 @@
     filename = request.form.get('filename', '')
     lines = str(request.form.get('lines', ''))
     if lines:
-        lines = lines.split(',')
+        lines = filter(None, [l.strip() for l in lines.split(',')])
     body = request.form['new-comment-body']
     
     if body: