changeset 3695:45df84d36b44 beta

Implemented preview for comments
author Marcin Kuzminski <marcin@python-works.com>
date Sat, 06 Apr 2013 02:49:42 +0200
parents 34093903b505
children e07b07ac9fbe
files rhodecode/config/routing.py rhodecode/controllers/changeset.py rhodecode/public/css/style.css rhodecode/public/js/rhodecode.js rhodecode/templates/base/root.html rhodecode/templates/changeset/changeset_file_comment.html
diffstat 6 files changed, 136 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/config/routing.py	Fri Apr 05 23:16:21 2013 +0200
+++ b/rhodecode/config/routing.py	Sat Apr 06 02:49:42 2013 +0200
@@ -500,6 +500,11 @@
                 controller='changeset', revision='tip', action='comment',
                 conditions=dict(function=check_repo))
 
+    rmap.connect('changeset_comment_preview',
+                 '/{repo_name:.*?}/changeset/comment/preview',
+                controller='changeset', action='preview_comment',
+                conditions=dict(function=check_repo, method=["POST"]))
+
     rmap.connect('changeset_comment_delete',
                  '/{repo_name:.*?}/changeset/comment/{comment_id}/delete',
                 controller='changeset', action='delete_comment',
--- a/rhodecode/controllers/changeset.py	Fri Apr 05 23:16:21 2013 +0200
+++ b/rhodecode/controllers/changeset.py	Sat Apr 06 02:49:42 2013 +0200
@@ -37,7 +37,8 @@
     ChangesetDoesNotExistError
 
 import rhodecode.lib.helpers as h
-from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
+from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\
+    NotAnonymous
 from rhodecode.lib.base import BaseRepoController, render
 from rhodecode.lib.utils import action_logger
 from rhodecode.lib.compat import OrderedDict
@@ -320,6 +321,7 @@
     def changeset_download(self, revision):
         return self.index(revision, method='download')
 
+    @NotAnonymous()
     @jsonify
     def comment(self, repo_name, revision):
         status = request.POST.get('changeset_status')
@@ -382,6 +384,16 @@
 
         return data
 
+    @NotAnonymous()
+    def preview_comment(self):
+        if not request.environ.get('HTTP_X_PARTIAL_XHR'):
+            raise HTTPBadRequest()
+        text = request.POST.get('text')
+        if text:
+            return h.rst_w_mentions(text)
+        return ''
+
+    @NotAnonymous()
     @jsonify
     def delete_comment(self, repo_name, comment_id):
         co = ChangesetComment.get(comment_id)
--- a/rhodecode/public/css/style.css	Fri Apr 05 23:16:21 2013 +0200
+++ b/rhodecode/public/css/style.css	Sat Apr 06 02:49:42 2013 +0200
@@ -218,6 +218,8 @@
 
 a.permalink {
     visibility: hidden;
+    position: absolute;
+    margin: 3px 4px;
 }
 
 a.permalink:hover {
@@ -4297,12 +4299,6 @@
     clear: both
 }
 
-.comment-form .clearfix {
-    background: #EEE;
-    -webkit-border-radius: 4px;
-    border-radius: 4px;
-    padding: 10px;
-}
 
 div.comment-form {
     margin-top: 20px;
@@ -4324,6 +4320,13 @@
     margin-left: 10px;
 }
 
+.comment-inline-form .comment-block-ta,
+.comment-form .comment-block-ta {
+    border: 1px solid #ccc;
+    border-radius: 3px;
+    box-sizing: border-box;
+}
+
 .comment-form-submit {
     margin-top: 5px;
     margin-left: 525px;
@@ -4338,9 +4341,22 @@
 }
 
 .comment-form .comment-help {
-    padding: 0px 0px 5px 0px;
+    padding: 5px 5px 5px 5px;
     color: #666;
 }
+.comment-form .comment-help .preview-btn,
+.comment-form .comment-help .edit-btn {
+    float: right;
+    margin: -6px 0px 0px 0px;
+}
+
+.comment-form .preview-box.unloaded,
+.comment-inline-form .preview-box.unloaded {
+    height: 50px;
+    text-align: center;
+    padding: 20px;
+    background-color: #fafafa;
+}
 
 .comment-form .comment-button {
     padding-top: 5px;
@@ -4354,7 +4370,7 @@
 
 .comment .buttons {
     float: right;
-    padding: 2px 2px 0px 0px;
+    margin: -1px 0px 0px 0px;
 }
 
 
@@ -4364,6 +4380,9 @@
 }
 
 /** comment inline form **/
+.comment-inline-form {
+    margin: 4px;
+}
 .comment-inline-form .overlay {
     display: none;
 }
@@ -4382,11 +4401,13 @@
     margin-top: 5%;
 }
 
-.comment-inline-form .clearfix {
+.comment-inline-form .clearfix,
+.comment-form .clearfix {
     background: #EEE;
     -webkit-border-radius: 4px;
     border-radius: 4px;
     padding: 5px;
+    margin: 0px;
 }
 
 div.comment-inline-form {
@@ -4423,9 +4444,14 @@
 }
 
 .comment-inline-form .comment-help {
-    padding: 0px 0px 2px 0px;
-    color: #666666;
-    font-size: 10px;
+    padding: 5px 5px 5px 5px;
+    color: #666;
+}
+
+.comment-inline-form .comment-help .preview-btn,
+.comment-inline-form .comment-help .edit-btn {
+    float: right;
+    margin: -6px 0px 0px 0px;
 }
 
 .comment-inline-form .comment-button {
--- a/rhodecode/public/js/rhodecode.js	Fri Apr 05 23:16:21 2013 +0200
+++ b/rhodecode/public/js/rhodecode.js	Sat Apr 06 02:49:42 2013 +0200
@@ -865,6 +865,29 @@
 		  
 		  ajaxPOST(submit_url, postData, success);
 	  });
+
+	  YUE.on('preview-btn_'+lineno, 'click', function(e){
+	       var _text = YUD.get('text_'+lineno).value;
+	       if(!_text){
+	           return
+	       }
+	       var post_data = {'text': _text};
+	       YUD.addClass('preview-box_'+lineno, 'unloaded');
+	       YUD.get('preview-box_'+lineno).innerHTML = _TM['Loading ...'];	       
+	       YUD.setStyle('edit-container_'+lineno, 'display', 'none');
+	       YUD.setStyle('preview-container_'+lineno, 'display', '');
+
+	       var url = pyroutes.url('changeset_comment_preview', {'repo_name': REPO_NAME});
+	       ajaxPOST(url,post_data,function(o){
+	           YUD.get('preview-box_'+lineno).innerHTML = o.responseText;
+	           YUD.removeClass('preview-box_'+lineno, 'unloaded');
+	       })
+	   })
+	   YUE.on('edit-btn_'+lineno, 'click', function(e){
+	       YUD.setStyle('edit-container_'+lineno, 'display', '');
+	       YUD.setStyle('preview-container_'+lineno, 'display', 'none');
+	   })	  
+	  
 	  
 	  setTimeout(function(){
 		  // callbacks
@@ -886,8 +909,11 @@
         var root = prevElementSibling(prevElementSibling(n));
         n.parentNode.removeChild(n);
 
-        // scann nodes, and attach add button to last one
-        placeAddButton(root);
+        // scann nodes, and attach add button to last one only for TR
+        // which are the inline comments
+        if(root && root.tagName == 'TR'){
+        	placeAddButton(root);
+        }
     }
     ajaxPOST(url,postData,success);
 }
--- a/rhodecode/templates/base/root.html	Fri Apr 05 23:16:21 2013 +0200
+++ b/rhodecode/templates/base/root.html	Sat Apr 06 02:49:42 2013 +0200
@@ -60,6 +60,10 @@
 
             var TOGGLE_FOLLOW_URL  = "${h.url('toggle_following')}";
 
+            var REPO_NAME = "";
+            %if hasattr(c, 'repo_name'):
+                var REPO_NAME = "${c.repo_name}";
+            %endif
             </script>
             <script type="text/javascript" src="${h.url('/js/yui.2.9.js', ver=c.rhodecode_version)}"></script>
             <!--[if lt IE 9]>
@@ -90,6 +94,7 @@
               pyroutes.register('toggle_following', "${h.url('toggle_following')}");
               pyroutes.register('changeset_info', "${h.url('changeset_info', repo_name='%(repo_name)s', revision='%(revision)s')}", ['repo_name', 'revision']);
               pyroutes.register('repo_size', "${h.url('repo_size', repo_name='%(repo_name)s')}", ['repo_name']);
+              pyroutes.register('changeset_comment_preview', "${h.url('changeset_comment_preview', repo_name='%(repo_name)s')}", ['repo_name']);
            })
             </script>
         </%def>
--- a/rhodecode/templates/changeset/changeset_file_comment.html	Fri Apr 05 23:16:21 2013 +0200
+++ b/rhodecode/templates/changeset/changeset_file_comment.html	Sat Apr 06 02:49:42 2013 +0200
@@ -12,7 +12,7 @@
               ${co.author.username}
           </div>
           <div class="date">
-              ${h.age(co.modified_at)} <a class="permalink" href="#comment-${co.comment_id}">&para;</a>
+              ${h.age(co.modified_at)}
           </div>
         %if co.status_change:
            <div  style="float:left" class="changeset-status-container">
@@ -22,7 +22,7 @@
            </div>
         %endif
 
-       <div style="float:left;padding:3px 0px 0px 5px">
+       <div style="float:left;padding:4px 0px 0px 5px">
         <span class="">
          %if co.pull_request:
             <a href="${h.url('pullrequest_show',repo_name=co.pull_request.other_repo.repo_name,pull_request_id=co.pull_request.pull_request_id)}">
@@ -35,11 +35,9 @@
          %endif
         </span>
        </div>
-
+      <a class="permalink" href="#comment-${co.comment_id}">&para;</a>
       %if h.HasPermissionAny('hg.admin', 'repository.admin')() or co.author.user_id == c.rhodecode_user.user_id:
-        <div class="buttons">
-          <span onClick="deleteComment(${co.comment_id})" class="delete-comment ui-btn">${_('Delete')}</span>
-        </div>
+          <div onClick="deleteComment(${co.comment_id})" class="buttons delete-comment ui-btn small">${_('Delete')}</div>
       %endif
       </div>
       <div class="text">
@@ -56,7 +54,7 @@
   %if c.rhodecode_user.username != 'default':
     <div class="overlay"><div class="overlay-text">${_('Submitting...')}</div></div>
       ${h.form('#', class_='inline-form')}
-      <div class="clearfix">
+      <div id="edit-container_{1}" class="clearfix">
           <div class="comment-help">${_('Commenting on line {1}.')}
           ${(_('Comments parsed using %s syntax with %s support.') % (
                  ('<a href="%s">RST</a>' % h.url('rst_help')),
@@ -64,9 +62,17 @@
                )
             )|n
            }
+          <div id="preview-btn_{1}" class="preview-btn ui-btn small">${_('preview')}</div>
           </div>
             <div class="mentions-container" id="mentions_container_{1}"></div>
-            <textarea id="text_{1}" name="text" class="yui-ac-input"></textarea>
+            <textarea id="text_{1}" name="text" class="comment-block-ta yui-ac-input"></textarea>
+      </div>
+      <div id="preview-container_{1}" class="clearfix" style="display:none">
+         <div class="comment-help">
+              ${_('Comment Preview')}
+            <div id="edit-btn_{1}" class="edit-btn ui-btn small">${_('edit')}</div>
+          </div>
+          <div id="preview-box_{1}" class="preview-box"></div>
       </div>
       <div class="comment-button">
       <input type="hidden" name="f_path" value="{0}">
@@ -134,7 +140,7 @@
     %if c.rhodecode_user.username != 'default':
     <div class="comment-form ac">
         ${h.form(post_url)}
-        <div class="clearfix">
+        <div id="edit-container" class="clearfix">
             <div class="comment-help">
                 ${(_('Comments parsed using %s syntax with %s support.') % (('<a href="%s">RST</a>' % h.url('rst_help')),
                   '<span style="color:#003367" class="tooltip" title="%s">@mention</span>' %
@@ -143,6 +149,7 @@
                 | <a id="show_changeset_link" onClick="change_status_show();"> ${_('Change status')}</a>
                   <input id="show_changeset_status_box" type="checkbox" name="change_changeset_status" style="display: none;" />
               %endif
+              <div id="preview-btn" class="preview-btn ui-btn small">${_('preview')}</div>
             </div>
             %if change_status:
             <div id="status_block_container" class="status-block" style="display:none">
@@ -155,8 +162,17 @@
             </div>
             %endif
             <div class="mentions-container" id="mentions_container"></div>
-             ${h.textarea('text')}
+             ${h.textarea('text', class_="comment-block-ta")}
         </div>
+
+        <div id="preview-container" class="clearfix" style="display:none">
+           <div class="comment-help">
+                ${_('Comment Preview')}
+              <div id="edit-btn" class="edit-btn ui-btn small">${_('edit')}</div>
+            </div>
+            <div id="preview-box" class="preview-box"></div>
+        </div>
+
         <div class="comment-button">
         ${h.submit('save', _('Comment'), class_="ui-btn large")}
         %if close_btn and change_status:
@@ -185,6 +201,27 @@
            YUD.addClass('save_close', 'hidden');
        }
    })
+   YUE.on('preview-btn', 'click', function(e){
+       var _text = YUD.get('text').value;
+       if(!_text){
+           return
+       }
+       var post_data = {'text': _text};
+       YUD.addClass('preview-box', 'unloaded');
+       YUD.get('preview-box').innerHTML = _TM['Loading ...'];
+       YUD.setStyle('edit-container', 'display', 'none');
+       YUD.setStyle('preview-container', 'display', '');
+
+       var url = pyroutes.url('changeset_comment_preview', {'repo_name': '${c.repo_name}'});
+       ajaxPOST(url,post_data,function(o){
+           YUD.get('preview-box').innerHTML = o.responseText;
+           YUD.removeClass('preview-box', 'unloaded');
+       })
+   })
+   YUE.on('edit-btn', 'click', function(e){
+       YUD.setStyle('edit-container', 'display', '');
+       YUD.setStyle('preview-container', 'display', 'none');
+   })
 
 });
 </script>