# HG changeset patch # User Marcin Kuzminski # Date 1321036913 -7200 # Node ID d2de0c2f02cd93e3f2a1b2bef9250b103621d456 # Parent f522f4d3bf93be2f2e47c3759d9dd1b962bcf9e2 #77 code review - initial very simple version of changeset comments - RST parsed diff -r f522f4d3bf93 -r d2de0c2f02cd rhodecode/config/routing.py --- a/rhodecode/config/routing.py Fri Nov 11 19:42:10 2011 +0200 +++ b/rhodecode/config/routing.py Fri Nov 11 20:41:53 2011 +0200 @@ -346,6 +346,14 @@ controller='changeset', revision='tip', conditions=dict(function=check_repo)) + rmap.connect('changeset_comment', '/{repo_name:.*}/changeset/{revision}/comment', + controller='changeset', revision='tip', action='comment', + conditions=dict(function=check_repo)) + + rmap.connect('changeset_comment_delete', '/{repo_name:.*}/changeset/comment/{comment_id}/delete', + controller='changeset', action='delete_comment', + conditions=dict(function=check_repo)) + rmap.connect('raw_changeset_home', '/{repo_name:.*}/raw-changeset/{revision}', controller='changeset', action='raw_changeset', diff -r f522f4d3bf93 -r d2de0c2f02cd rhodecode/controllers/changeset.py --- a/rhodecode/controllers/changeset.py Fri Nov 11 19:42:10 2011 +0200 +++ b/rhodecode/controllers/changeset.py Fri Nov 11 20:41:53 2011 +0200 @@ -29,15 +29,19 @@ from pylons import tmpl_context as c, url, request, response from pylons.i18n.translation import _ from pylons.controllers.util import redirect +from pylons.decorators import jsonify 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 EmptyChangeset from rhodecode.lib.compat import OrderedDict +from rhodecode.model.db import ChangesetComment +from rhodecode.model.comment import ChangesetCommentsModel from vcs.exceptions import RepositoryError, ChangesetError, \ -ChangesetDoesNotExistError + ChangesetDoesNotExistError from vcs.nodes import FileNode from vcs.utils import diffs as differ @@ -66,7 +70,7 @@ #get ranges of revisions if preset rev_range = revision.split('...')[:2] - + try: if len(rev_range) == 2: rev_start = rev_range[0] @@ -92,6 +96,14 @@ c.lines_deleted = 0 c.cut_off = False # defines if cut off limit is reached + c.comments = [] + for cs in c.cs_ranges: + c.comments.extend(ChangesetComment.query()\ + .filter(ChangesetComment.repo_id == c.rhodecode_db_repo.repo_id)\ + .filter(ChangesetComment.commit_id == cs.raw_id)\ + .filter(ChangesetComment.line_no == None)\ + .filter(ChangesetComment.f_path == None).all()) + # Iterate over ranges (default changeset view is always one changeset) for changeset in c.cs_ranges: c.changes[changeset.raw_id] = [] @@ -252,3 +264,22 @@ c.diffs += x[2] return render('changeset/raw_changeset.html') + + def comment(self, repo_name, revision): + ccmodel = ChangesetCommentsModel() + + ccmodel.create(text=request.POST.get('text'), + repo_id=c.rhodecode_db_repo.repo_id, + user_id=c.rhodecode_user.user_id, + commit_id=revision, f_path=request.POST.get('f_path'), + line_no = request.POST.get('line')) + + return redirect(h.url('changeset_home', repo_name=repo_name, + revision=revision)) + + @jsonify + @HasRepoPermissionAnyDecorator('hg.admin', 'repository.admin') + def delete_comment(self, comment_id): + ccmodel = ChangesetCommentsModel() + ccmodel.delete(comment_id=comment_id) + return True diff -r f522f4d3bf93 -r d2de0c2f02cd rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py Fri Nov 11 19:42:10 2011 +0200 +++ b/rhodecode/lib/helpers.py Fri Nov 11 20:41:53 2011 +0200 @@ -39,6 +39,8 @@ from rhodecode.lib.utils import repo_name_slug from rhodecode.lib import str2bool, safe_unicode, safe_str, get_changeset_safe +from rhodecode.lib.markup_renderer import MarkupRenderer + def _reset(name, value=None, id=NotGiven, type="reset", **attrs): """ Reset button @@ -531,7 +533,7 @@ self.last_item = ((self.item_count - 1) - items_per_page * (self.page - 1)) - self.items = list(self.collection[self.first_item:self.last_item+1]) + self.items = list(self.collection[self.first_item:self.last_item + 1]) # Links to previous and next page @@ -668,3 +670,6 @@ return literal(url_pat.sub(url_func, text)) + +def rst(source): + return literal('
%s
' % MarkupRenderer.rst(source)) diff -r f522f4d3bf93 -r d2de0c2f02cd rhodecode/model/comment.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rhodecode/model/comment.py Fri Nov 11 20:41:53 2011 +0200 @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +""" + rhodecode.model.comment + ~~~~~~~~~~~~~~~~~~~~~~~ + + comments model for RhodeCode + + :created_on: Nov 11, 2011 + :author: marcink + :copyright: (C) 2009-2011 Marcin Kuzminski + :license: GPLv3, see COPYING for more details. +""" +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +import logging +import traceback + +from rhodecode.model import BaseModel +from rhodecode.model.db import ChangesetComment + +log = logging.getLogger(__name__) + + +class ChangesetCommentsModel(BaseModel): + + + def create(self, text, repo_id, user_id, commit_id, f_path=None, + line_no=None): + """ + Creates new comment for changeset + + :param text: + :param repo_id: + :param user_id: + :param commit_id: + :param f_path: + :param line_no: + """ + + comment = ChangesetComment() + comment.repo_id = repo_id + comment.user_id = user_id + comment.commit_id = commit_id + comment.text = text + comment.f_path = f_path + comment.line_no = line_no + + self.sa.add(comment) + self.sa.commit() + return comment + + def delete(self, comment_id): + """ + Deletes given comment + + :param comment_id: + """ + comment = ChangesetComment.get(comment_id) + self.sa.delete(comment) + self.sa.commit() + return comment diff -r f522f4d3bf93 -r d2de0c2f02cd rhodecode/model/db.py --- a/rhodecode/model/db.py Fri Nov 11 19:42:10 2011 +0200 +++ b/rhodecode/model/db.py Fri Nov 11 20:41:53 2011 +0200 @@ -1095,6 +1095,22 @@ Session.commit() +class ChangesetComment(Base, BaseModel): + __tablename__ = 'changeset_comments' + __table_args__ = ({'extend_existing':True},) + comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) + repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) + commit_id = Column('commit_id', String(100), nullable=False) + line_no = Column('line_no', Integer(), nullable=True) + f_path = Column('f_path', String(1000), nullable=True) + user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False) + text = Column('text', String(25000), nullable=False) + modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) + + author = relationship('User') + repo = relationship('Repository') + + class DbMigrateVersion(Base, BaseModel): __tablename__ = 'db_migrate_version' __table_args__ = {'extend_existing':True} diff -r f522f4d3bf93 -r d2de0c2f02cd rhodecode/public/css/diff.css --- a/rhodecode/public/css/diff.css Fri Nov 11 19:42:10 2011 +0200 +++ b/rhodecode/public/css/diff.css Fri Nov 11 20:41:53 2011 +0200 @@ -8,6 +8,11 @@ /* new */ line-height: 125%; } + +div.diffblock.margined{ + margin: 0px 20px 0px 20px; +} + div.diffblock .code-header{ border-bottom: 1px solid #CCCCCC; background: #EEEEEE; diff -r f522f4d3bf93 -r d2de0c2f02cd rhodecode/public/css/style.css --- a/rhodecode/public/css/style.css Fri Nov 11 19:42:10 2011 +0200 +++ b/rhodecode/public/css/style.css Fri Nov 11 20:41:53 2011 +0200 @@ -3135,3 +3135,201 @@ -moz-border-radius: 3px; border-radius: 3px; } + + +/** RST STYLE **/ + + +div.rst-block { + padding:0px; +} + +div.rst-block h2 { + font-weight: normal; +} + +div.rst-block { + background-color: #fafafa; +} + +div.rst-block { +clear:both; +overflow:hidden; +margin:0; +padding:0 20px 10px; +} + +div.rst-block h1, div.rst-block h2, div.rst-block h3, div.rst-block h4, div.rst-block h5, div.rst-block h6 { +border-bottom: 0 !important; +margin: 0 !important; +padding: 0 !important; +line-height: 1.5em !important; +} + + +div.rst-block h1:first-child { +padding-top: .25em !important; +} + +div.rst-block h2, div.rst-block h3 { +margin: 1em 0 !important; +} + +div.rst-block h2 { +margin-top: 1.5em !important; +border-top: 4px solid #e0e0e0 !important; +padding-top: .5em !important; +} + +div.rst-block p { +color: black !important; +margin: 1em 0 !important; +line-height: 1.5em !important; +} + +div.rst-block ul { +list-style: disc !important; +margin: 1em 0 1em 2em !important; +} + +div.rst-block ol { +list-style: decimal; +margin: 1em 0 1em 2em !important; +} + +div.rst-block pre, code { +font: 12px "Bitstream Vera Sans Mono","Courier",monospace; +} + +div.rst-block code { + font-size: 12px !important; + background-color: ghostWhite !important; + color: #444 !important; + padding: 0 .2em !important; + border: 1px solid #dedede !important; +} + +div.rst-block pre code { + padding: 0 !important; + font-size: 12px !important; + background-color: #eee !important; + border: none !important; +} + +div.rst-block pre { + margin: 1em 0; + font-size: 12px; + background-color: #eee; + border: 1px solid #ddd; + padding: 5px; + color: #444; + overflow: auto; + -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + + + +.comments { + padding:10px 20px; +} + +.comments .comment { + border: 1px solid #ddd; + margin-top: 10px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.comments .comment .meta { + background: #f8f8f8; + padding: 6px; + border-bottom: 1px solid #ddd; +} + +.comments .comment .meta img { + vertical-align: middle; +} + +.comments .comment .meta .user { + font-weight: bold; +} + +.comments .comment .meta .date { + float: right; +} + +.comments .comment .text { + margin-top: 7px; + padding: 6px; + padding-bottom: 13px; +} + +.comments .comments-number{ + padding:0px 0px 10px 0px; + font-weight: bold; +} + +.comment-form .clearfix{ + background: #EEE; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + padding: 10px; +} + +div.comment-form { + margin-top: 20px; +} + +.comment-form strong { + display: block; + margin-bottom: 15px; +} + +.comment-form textarea { + width: 100%; + height: 100px; + font-family: 'Monaco', 'Courier', 'Courier New', monospace; +} + +form.comment-form { + margin-top: 10px; + margin-left: 10px; +} + +.comment-form-submit { + margin-top: 5px; + margin-left: 525px; +} + +.file-comments { + display: none; +} + +.comment-form .comment { + margin-left: 10px; +} + +.comment-form .comment-help{ + padding: 0px 0px 5px 0px; + color: #666; +} + +.comment-form .comment-button{ + padding-top:5px; +} + +.add-another-button { + margin-left: 10px; + margin-top: 10px; + margin-bottom: 10px; +} + +.comment .buttons { + float: right; + display: none; +} diff -r f522f4d3bf93 -r d2de0c2f02cd rhodecode/templates/changeset/changeset.html --- a/rhodecode/templates/changeset/changeset.html Fri Nov 11 19:42:10 2011 +0200 +++ b/rhodecode/templates/changeset/changeset.html Fri Nov 11 20:41:53 2011 +0200 @@ -108,7 +108,7 @@ %for change,filenode,diff,cs1,cs2,stat in c.changes: %if change !='removed':
-
+
@@ -134,6 +134,30 @@
%endif - %endfor -
+ %endfor + + <%namespace name="comment" file="/changeset/changeset_file_comment.html"/> + +
+
${len(c.comments)} comment(s)
+ %for co in c.comments: + ${comment.comment_block(co)} + %endfor + %if c.rhodecode_user.username != 'default': +
+ ${h.form(h.url('changeset_comment', repo_name=c.repo_name, revision=c.changeset.raw_id))} + Leave a comment +
+
${_('Comments parsed using RST syntax')}
+ ${h.textarea('text')} +
+
+ ${h.submit('save', _('Comment'), class_='ui-button')} +
+ ${h.end_form()} +
+ %endif +
+ +
diff -r f522f4d3bf93 -r d2de0c2f02cd rhodecode/templates/changeset/changeset_file_comment.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rhodecode/templates/changeset/changeset_file_comment.html Fri Nov 11 20:41:53 2011 +0200 @@ -0,0 +1,31 @@ +##usage: +## <%namespace name="comment" file="/changeset/changeset_file_comment.html"/> +## ${comment.comment_block(co)} +## +<%def name="comment_block(co)"> +
+
+ + + ${co.author.username} + + ${_('commented on')} + ${h.short_id(co.commit_id)} + %if co.f_path: + ${_(' in file ')} + ${co.f_path}:L${co.line_no} + %endif + + ${h.age(co.modified_at)} + +
+
+ %if h.HasPermissionAny('hg.admin', 'repository.admin')() or co.author.user_id == c.rhodecode_user.user_id: + + %endif + ${h.rst(co.text)|n} +
+
+ \ No newline at end of file