Changeset - 051624cb5f3a
[Not reviewed]
default
0 2 0
Thomas De Schampheleire - 11 years ago 2015-01-27 22:03:55
thomas.de_schampheleire@alcatel-lucent.com
comment handling: clarify shown comment count (inline vs general)

Instead of showing the number of comments as:
y comments (z inline)
show it as:
x comments (z inline, y general)
2 files changed with 11 insertions and 7 deletions:
0 comments (0 inline, 0 general)
kallithea/templates/changeset/changeset_file_comment.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
## usage:
 
## <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
 
## ${comment.comment_block(co)}
 
##
 
<%def name="comment_block(co)">
 
  <div class="comment" id="comment-${co.comment_id}" line="${co.line_no}">
 
    <div class="comment-wrapp">
 
      <div class="meta">
 
          <div style="float:left">
 
               ${h.gravatar(co.author.email, size=20)}
 
          </div>
 
          <div class="user">
 
              ${co.author.username}
 
          </div>
 
          <div class="date">
 
              ${h.age(co.modified_at)}
 
          </div>
 

	
 
       <div style="float:left;padding:4px 0px 0px 5px">
 
        <span class="">
 
         %if co.pull_request:
 
            %if co.status_change:
 
              ${_('Status change from pull request')}
 
              <a href="${co.pull_request.url()}">"${co.pull_request.title or _("No title")}"</a>:
 
            %else:
 
              ${_('Comment from pull request')}
 
              <a href="${co.pull_request.url()}">"${co.pull_request.title or _("No title")}"</a>
 
            %endif
 
         %else:
 
            %if co.status_change:
 
              ${_('Status change on changeset')}:
 
            %else:
 
              ${_('Comment on changeset')}
 
            %endif
 
         %endif
 
        </span>
 
       </div>
 

	
 
        %if co.status_change:
 
           <div  style="float:left" class="changeset-status-container">
 
             <div style="float:left;padding:10px 2px 0px 2px"></div>
 
             <div title="${_('Changeset status')}" class="changeset-status-lbl"> ${co.status_change[0].status_lbl}</div>
 
             <div class="changeset-status-ico"><i class="icon-circle changeset-status-${co.status_change[0].status}"></i></div>
 
           </div>
 
        %endif
 

	
 
      <a class="permalink" href="#comment-${co.comment_id}">&para;</a>
 
      %if h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or co.author.user_id == c.authuser.user_id:
 
          <div onClick="confirm('${_("Delete comment?")}') && deleteComment(${co.comment_id})" class="buttons delete-comment btn btn-mini">${_('Delete')}</div>
 
      %endif
 
      </div>
 
      <div class="text">
 
          ${h.rst_w_mentions(co.text)|n}
 
      </div>
 
    </div>
 
  </div>
 
</%def>
 

	
 

	
 
<%def name="comment_inline_form()">
 
<div id='comment-inline-form-template' style="display:none">
 
  <div class="comment-inline-form ac">
 
  %if c.authuser.username != 'default':
 
    ${h.form('#', class_='inline-form')}
 
      <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')),
 
                   ('<span style="color:#577632" class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to notify another user'))
 
               )
 
            )|n
 
           }
 
        </div>
 
        <div class="mentions-container" id="mentions_container_{1}"></div>
 
        <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>
 
        <div id="preview-box_{1}" class="preview-box"></div>
 
      </div>
 
      <div class="comment-button">
 
        <div class="submitting-overlay">${_('Submitting ...')}</div>
 
        <input type="hidden" name="f_path" value="{0}">
 
        <input type="hidden" name="line" value="{1}">
 
        ${h.submit('save', _('Comment'), class_='btn btn-small save-inline-form')}
 
        ${h.reset('hide-inline-form', _('Cancel'), class_='btn btn-small hide-inline-form')}
 
        <div id="preview-btn_{1}" class="preview-btn btn btn-small">${_('Preview')}</div>
 
        <div id="edit-btn_{1}" class="edit-btn btn btn-small" style="display:none">${_('Edit')}</div>
 
      </div>
 
    ${h.end_form()}
 
  %else:
 
      ${h.form('')}
 
      <div class="clearfix">
 
          <div class="comment-help">
 
            ${_('You need to be logged in to comment.')} <a href="${h.url('login_home',came_from=h.url.current())}">${_('Login now')}</a>
 
          </div>
 
      </div>
 
      <div class="comment-button">
 
      ${h.reset('hide-inline-form', _('Hide'), class_='btn btn-small hide-inline-form')}
 
      </div>
 
      ${h.end_form()}
 
  %endif
 
  </div>
 
</div>
 
</%def>
 

	
 

	
 
## show comment count
 
## show comment count as "x comments (y inline, z general)"
 
<%def name="comment_count(inline_cnt, general_cnt)">
 
${ungettext("%d comment", "%d comments", general_cnt) % general_cnt} ${ungettext("(%d inline)", "(%d inline)", inline_cnt) % inline_cnt}
 
<span class="firstlink"></span>
 
    ${'%s (%s, %s)' % (
 
        ungettext("%d comment", "%d comments", inline_cnt + general_cnt) % (inline_cnt + general_cnt),
 
        ungettext("%d inline", "%d inline", inline_cnt) % inline_cnt,
 
        ungettext("%d general", "%d general", general_cnt) % general_cnt
 
    )}
 
    <span class="firstlink"></span>
 
</%def>
 

	
 
## generates inlines taken from c.comments var
 
<%def name="inlines()">
 
    <div class="comments-number">
 
        ${comment_count(c.inline_cnt, len(c.comments))}
 
    </div>
 
    %for path, lines in c.inline_comments:
 
        % for line,comments in lines.iteritems():
 
            <div style="display:none" class="inline-comment-placeholder" path="${path}" target_id="${h.safeid(h.safe_unicode(path))}">
 
            %for co in comments:
 
                ${comment_block(co)}
 
            %endfor
 
            </div>
 
        %endfor
 
    %endfor
 

	
 
</%def>
 

	
 
## generate inline comments and the main ones
 
<%def name="generate_comments()">
 
<div class="comments">
 
    <div id="inline-comments-container">
 
    ## generate inlines for this changeset
 
     ${inlines()}
 
    </div>
 

	
 
    %for co in c.comments:
 
        <div id="comment-tr-${co.comment_id}">
 
          ${comment_block(co)}
 
        </div>
 
    %endfor
 
</div>
 
</%def>
 

	
 
## MAIN COMMENT FORM
 
<%def name="comments(post_url, cur_status, is_pr=False, change_status=True)">
 

	
 
<div class="comments">
 
    %if c.authuser.username != 'default':
 
    <div class="comment-form ac">
 
      ${h.form(post_url)}
 
        <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:#577632" class="tooltip" title="%s">@mention</span>' %
 
                  _('Use @username inside this text to send notification to another local user.')))|n}
 
            </div>
 
            <div class="mentions-container" id="mentions_container"></div>
 
            ${h.textarea('text', class_="comment-block-ta")}
 
            %if change_status:
 
              <div id="status_block_container" class="status-block">
 
                %if is_pr:
 
                  ${_('Vote for pull request status')}:
 
                %else:
 
                  ${_('Set changeset status')}:
 
                %endif
 
                <input type="radio" class="status_change_radio" name="changeset_status" id="changeset_status_unchanged" value="" checked="checked" />
 
                <label for="changeset_status_unchanged">
 
                  ${_('No change')}
 
                </label>
 
                %for status,lbl in c.changeset_statuses:
 
                    <span style="margin-left: 15px;">
 
                        <input type="radio" class="status_change_radio" name="changeset_status" id="${status}" value="${status}">
 
                        <label for="${status}"><i class="icon-circle changeset-status-${status}" /></i>${lbl}</label>
 
                    </span>
 
                %endfor
 
                %if is_pr and change_status:
 
                <input id="save_close" type="checkbox" name="save_close">
 
                <label id="save_close_label" for="save_close">${_("Close")}</label>
 
                %endif
 
              </div>
 
            %endif
 
        </div>
 

	
 
        <div id="preview-container" class="clearfix" style="display:none">
 
            <div class="comment-help">
 
                ${_('Comment preview')}
 
            </div>
 
            <div id="preview-box" class="preview-box"></div>
 
        </div>
 

	
 
        <div class="comment-button">
 
            ${h.submit('save', _('Comment'), class_="btn")}
 
            <div id="preview-btn" class="preview-btn btn">${_('Preview')}</div>
 
            <div id="edit-btn" class="edit-btn btn" style="display:none">${_('Edit')}</div>
 
        </div>
 
      ${h.end_form()}
 
    </div>
 
    %endif
 
</div>
 

	
 
<script>
 

	
 
$(document).ready(function () {
 
   MentionsAutoComplete('text', 'mentions_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
 

	
 
   $(window).on('beforeunload', function(){
 
      if($('.form-open').size() || $('textarea#text').val()){
 
         // this message will not be displayed on all browsers
 
         // (e.g. some versions of Firefox), but the user will still be warned
 
         return 'There are uncommitted comments.';
 
      }
 
   });
 

	
 
   $('#preview-btn').click(function(){
 
       var _text = $('#text').val();
 
       if(!_text){
 
           return;
 
       }
 
       var post_data = {'text': _text};
 
       $('#preview-box').addClass('unloaded');
 
       $('#preivew-box').html(_TM['Loading ...']);
 
       $('#edit-container').hide();
 
       $('#edit-btn').show();
 
       $('#preview-container').show();
 
       $('#preview-btn').hide();
 

	
 
       var url = pyroutes.url('changeset_comment_preview', {'repo_name': '${c.repo_name}'});
 
       ajaxPOST(url,post_data,function(html){
 
           $('#preview-box').html(html);
 
           $('#preview-box').removeClass('unloaded');
 
       });
 
   });
 
   $('#edit-btn').click(function(){
 
       $('#edit-container').show();
 
       $('#edit-btn').hide();
 
       $('#preview-container').hide();
 
       $('#preview-btn').show();
 
   });
 

	
 
});
 
</script>
 
</%def>
kallithea/tests/functional/test_changeset_comments.py
Show inline comments
 
from kallithea.tests import *
 
from kallithea.model.db import ChangesetComment, Notification, \
 
    UserNotification
 
from kallithea.model.meta import Session
 

	
 

	
 
class TestChangeSetCommentsController(TestController):
 

	
 
    def setUp(self):
 
        for x in ChangesetComment.query().all():
 
            Session().delete(x)
 
        Session().commit()
 

	
 
        for x in Notification.query().all():
 
            Session().delete(x)
 
        Session().commit()
 

	
 
    def tearDown(self):
 
        for x in ChangesetComment.query().all():
 
            Session().delete(x)
 
        Session().commit()
 

	
 
        for x in Notification.query().all():
 
            Session().delete(x)
 
        Session().commit()
 

	
 
    def test_create(self):
 
        self.log_user()
 
        rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
 
        text = u'CommentOnRevision'
 

	
 
        params = {'text': text}
 
        response = self.app.post(url(controller='changeset', action='comment',
 
                                     repo_name=HG_REPO, revision=rev),
 
                                     params=params)
 
        # Test response...
 
        self.assertEqual(response.status, '302 Found')
 
        response.follow()
 

	
 
        response = self.app.get(url(controller='changeset', action='index',
 
                                repo_name=HG_REPO, revision=rev))
 
        # test DB
 
        self.assertEqual(ChangesetComment.query().count(), 1)
 
        response.mustcontain(
 
            '''<div class="comments-number">'''
 
            ''' 1 comment (0 inline)'''
 
            ''' 1 comment (0 inline, 1 general)'''
 
        )
 

	
 
        self.assertEqual(Notification.query().count(), 1)
 
        self.assertEqual(ChangesetComment.query().count(), 1)
 

	
 
        notification = Notification.query().all()[0]
 

	
 
        ID = ChangesetComment.query().first().comment_id
 
        self.assertEqual(notification.type_,
 
                         Notification.TYPE_CHANGESET_COMMENT)
 
        sbj = (u'/vcs_test_hg/changeset/'
 
               '27cd5cce30c96924232dffcd24178a07ffeb5dfc#comment-%s' % ID)
 
        print "%s vs %s" % (sbj, notification.subject)
 
        self.assertTrue(sbj in notification.subject)
 

	
 
    def test_create_inline(self):
 
        self.log_user()
 
        rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
 
        text = u'CommentOnRevision'
 
        f_path = 'vcs/web/simplevcs/views/repository.py'
 
        line = 'n1'
 

	
 
        params = {'text': text, 'f_path': f_path, 'line': line}
 
        response = self.app.post(url(controller='changeset', action='comment',
 
                                     repo_name=HG_REPO, revision=rev),
 
                                     params=params)
 
        # Test response...
 
        self.assertEqual(response.status, '302 Found')
 
        response.follow()
 

	
 
        response = self.app.get(url(controller='changeset', action='index',
 
                                repo_name=HG_REPO, revision=rev))
 
        #test DB
 
        self.assertEqual(ChangesetComment.query().count(), 1)
 
        response.mustcontain(
 
            '''<div class="comments-number">'''
 
            ''' 0 comments (1 inline)'''
 
            ''' 1 comment (1 inline, 0 general)'''
 
        )
 
        response.mustcontain(
 
            '''<div style="display:none" class="inline-comment-placeholder" '''
 
            '''path="vcs/web/simplevcs/views/repository.py" '''
 
            '''target_id="vcswebsimplevcsviewsrepositorypy">'''
 
        )
 

	
 
        self.assertEqual(Notification.query().count(), 1)
 
        self.assertEqual(ChangesetComment.query().count(), 1)
 

	
 
        notification = Notification.query().all()[0]
 
        ID = ChangesetComment.query().first().comment_id
 
        self.assertEqual(notification.type_,
 
                         Notification.TYPE_CHANGESET_COMMENT)
 
        sbj = (u'/vcs_test_hg/changeset/'
 
               '27cd5cce30c96924232dffcd24178a07ffeb5dfc#comment-%s' % ID)
 
        print "%s vs %s" % (sbj, notification.subject)
 
        self.assertTrue(sbj in notification.subject)
 

	
 
    def test_create_with_mention(self):
 
        self.log_user()
 

	
 
        rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
 
        text = u'@test_regular check CommentOnRevision'
 

	
 
        params = {'text':text}
 
        response = self.app.post(url(controller='changeset', action='comment',
 
                                     repo_name=HG_REPO, revision=rev),
 
                                     params=params)
 
        # Test response...
 
        self.assertEqual(response.status, '302 Found')
 
        response.follow()
 

	
 
        response = self.app.get(url(controller='changeset', action='index',
 
                                repo_name=HG_REPO, revision=rev))
 
        # test DB
 
        self.assertEqual(ChangesetComment.query().count(), 1)
 
        response.mustcontain(
 
            '''<div class="comments-number">'''
 
            ''' 1 comment (0 inline)'''
 
            ''' 1 comment (0 inline, 1 general)'''
 
        )
 

	
 
        self.assertEqual(Notification.query().count(), 2)
 
        users = [x.user.username for x in UserNotification.query().all()]
 

	
 
        # test_regular gets notification by @mention
 
        self.assertEqual(sorted(users), [u'test_admin', u'test_regular'])
 

	
 
    def test_delete(self):
 
        self.log_user()
 
        rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
 
        text = u'CommentOnRevision'
 

	
 
        params = {'text': text}
 
        response = self.app.post(url(controller='changeset', action='comment',
 
                                     repo_name=HG_REPO, revision=rev),
 
                                     params=params)
 

	
 
        comments = ChangesetComment.query().all()
 
        self.assertEqual(len(comments), 1)
 
        comment_id = comments[0].comment_id
 

	
 
        self.app.delete(url(controller='changeset',
 
                                    action='delete_comment',
 
                                    repo_name=HG_REPO,
 
                                    comment_id=comment_id))
 

	
 
        comments = ChangesetComment.query().all()
 
        self.assertEqual(len(comments), 0)
 

	
 
        response = self.app.get(url(controller='changeset', action='index',
 
                                repo_name=HG_REPO, revision=rev))
 
        response.mustcontain(
 
            '''<div class="comments-number">'''
 
            ''' 0 comments (0 inline)'''
 
            ''' 0 comments (0 inline, 0 general)'''
 
        )
0 comments (0 inline, 0 general)