Started ticket 39, add code review.

We now have a limited support of the code review. Still some work to be
done to allow the submission of new patches on a given review and update
the status. For the moment, only pre-commit review is supported.
This commit is contained in:
Loic d'Anterroches
2008-11-30 10:26:05 +01:00
parent fbe364462d
commit f690968b11
35 changed files with 2422 additions and 8 deletions

View File

@@ -36,6 +36,12 @@
</td>
</tr>
<tr>
<th><strong>{$form.f.review_access_rights.labelTag}:</strong></th>
<td>{if $form.f.review_access_rights.errors}{$form.f.review_access_rights.fieldErrors}{/if}
{$form.f.review_access_rights|unsafe}
</td>
</tr>
<tr>
<th>{if $form.f.private_project.errors}{$form.f.private_project.fieldErrors}{/if}
{$form.f.private_project|unsafe}
</th>

View File

@@ -0,0 +1,87 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
{*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors.
#
# InDefero 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 2 of the License, or
# (at your option) any later version.
#
# InDefero 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, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK *****
*}<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="{media '/idf/css/yui.css'}" />
<link rel="stylesheet" type="text/css" href="{media '/idf/css/style.css'}" />
<!--[if lt IE 7]>
<link rel="stylesheet" type="text/css" href="{media '/idf/css/ie6.css'}" />
<![endif]-->
{block extraheader}{/block}
<title>{block pagetitle}{$page_title|strip_tags}{/block}</title>
</head>
<body>
<div id="{block docid}doc3{/block}">
<div id="hd">
{if $project}<h1 class="project-title">{$project}</h1>{/if}
<p class="top"><a href="#title" accesskey="2"></a>
{if !$user.isAnonymous()}{aurl 'url', 'IDF_Views_User::myAccount'}{blocktrans}Welcome, <strong><a class="userw" href="{$url}">{$user}</a></strong>.{/blocktrans} <a href="{url 'IDF_Views::logout'}">{trans 'Sign Out'}</a>{else}<a href="{url 'IDF_Views::login'}">{trans 'Sign in or create your account'}</a>{/if}
{if $project} | <a href="{url 'IDF_Views::index'}">{trans 'Project List'}</a>{/if}
| <a href="{url 'IDF_Views::faq'}" title="{trans 'Help and accessibility features'}">{trans 'Help'}</a>
</p>
<div id="header">
<div id="main-tabs">
{if $project}
<a accesskey="1" href="{url 'IDF_Views_Project::home', array($project.shortname)}"{block tabhome}{/block}>{trans 'Project Home'}</a>
{if $hasDownloadsAccess} <a href="{url 'IDF_Views_Download::index', array($project.shortname)}"{block tabdownloads}{/block}>{trans 'Downloads'}</a>{/if}
{if $hasWikiAccess} <a href="{url 'IDF_Views_Wiki::index', array($project.shortname)}"{block tabwiki}{/block}>{trans 'Documentation'}</a>{/if}
{if $hasIssuesAccess} <a href="{url 'IDF_Views_Issue::index', array($project.shortname)}"{block tabissues}{/block}>{trans 'Issues'}</a>{/if}
{if $hasSourceAccess} <a href="{url 'IDF_Views_Source::treeBase', array($project.shortname, $project.getScmRoot())}"{block tabsource}{/block}>{trans 'Source'}</a>{/if}
{if $hasReviewAccess} <a href="{url 'IDF_Views_Review::index', array($project.shortname)}"{block tabreview}{/block}>{trans 'Code Review'}</a>{/if}
{if $isOwner}
<a href="{url 'IDF_Views_Project::admin', array($project.shortname)}"{block tabadmin}{/block}>{trans 'Administer'}</a>{/if}{/if}
</div>
{block subtabs}{if $user.isAnonymous()} | {aurl 'url', 'IDF_Views::login'}{blocktrans}<a href="{$url}">Sign in or create your account</a> to create issues or add comments{/blocktrans}{/if}{/block}
</div>
<h1 class="title" id="title">{block titleicon}{/block}{block title}{$page_title}{/block}</h1>
</div>
<div id="bd">
<div id="yui-main">
<div class="yui-b">
<div class="yui-g">
{if $user and $user.id}{getmsgs $user}{/if}
<div class="content">{block body}{/block}</div>
</div>
</div>
</div>
</div>
<div id="ft">{block foot}{/block}</div>
</div>
<script type="text/javascript" src="{media '/idf/js/jquery-1.2.6.min.js'}"></script>
{include 'idf/js-hotkeys.html'}
{block javascript}{/block}
{if $project}
<script type="text/javascript">{literal}
<!-- //
$(document).ready(function(){
var frag = location.hash;
if (frag.length > 3 && frag.substring(0, 3) == '#ic') {
$(frag).addClass("issue-comment-focus");
}
});
// -->{/literal}
</script>{/if}
</body>
</html>

View File

@@ -51,7 +51,7 @@
</div>
<div class="yui-b context">{block context}{/block}</div>
</div>
<div id="ft">{block foot}<a href="http://www.indefero.net" title="InDefero, bug tracking and more"><img src="{media '/idf/img/powered-by-indefero.png'}" alt="InDefero Logo" /></a>{/block}</div>
<div id="ft">{block foot}{/block}</div>
</div>
<script type="text/javascript" src="{media '/idf/js/jquery-1.2.6.min.js'}"></script>
{include 'idf/js-hotkeys.html'}

View File

@@ -47,6 +47,7 @@
{if $hasWikiAccess} <a href="{url 'IDF_Views_Wiki::index', array($project.shortname)}"{block tabwiki}{/block}>{trans 'Documentation'}</a>{/if}
{if $hasIssuesAccess} <a href="{url 'IDF_Views_Issue::index', array($project.shortname)}"{block tabissues}{/block}>{trans 'Issues'}</a>{/if}
{if $hasSourceAccess} <a href="{url 'IDF_Views_Source::treeBase', array($project.shortname, $project.getScmRoot())}"{block tabsource}{/block}>{trans 'Source'}</a>{/if}
{if $hasReviewAccess} <a href="{url 'IDF_Views_Review::index', array($project.shortname)}"{block tabreview}{/block}>{trans 'Code Review'}</a>{/if}
{if $isOwner}
<a href="{url 'IDF_Views_Project::admin', array($project.shortname)}"{block tabadmin}{/block}>{trans 'Administer'}</a>{/if}{/if}
</div>

View File

@@ -13,3 +13,4 @@
{block context}
<p><strong>{trans 'Managed Projects:'}</strong> {$projects.count()}</p>
{/block}
{block foot}<div id="branding">Powered by <a href="http://www.indefero.net" title="InDefero, bug tracking and more">InDefero</a>,<br />a <a href="http://www.ceondo.com">Céondo Ltd</a> initiative.</div>{/block}

View File

@@ -113,7 +113,6 @@ $(document).ready(function(){
}
});
</script>
{/literal}{/block}
{/literal}
{include 'idf/issues/js-autocomplete.html'}{/block}

View File

@@ -40,4 +40,4 @@
</p>
{/block}
{block foot}<div id="branding">Powered by <a href="http://www.indefero.net" title="InDefero, bug tracking and more">InDefero</a>,<br />a <a href="http://www.ceondo.com">Céondo Ltd</a> initiative.</div>{/block}

View File

@@ -0,0 +1,15 @@
{extends "idf/base-full.html"}
{block tabreview} class="active"{/block}
{block subtabs}
<div id="sub-tabs">
<a {if $inOpenReviews}class="active" {/if}href="{url 'IDF_Views_Review::index', array($project.shortname)}">{trans 'Open Reviews'}</a> {*
{if !$user.isAnonymous()} | <a {if $inCreate}class="active" {/if}href="{url 'IDF_Views_Issue::create', array($project.shortname)}">{trans 'New Issue'}</a> | <a {if $inMyIssues}class="active" {/if}href="{url 'IDF_Views_Issue::myIssues', array($project.shortname, 'submit')}">{trans 'My Issues'}</a>{/if} |
<form class="star" action="{url 'IDF_Views_Issue::search', array($project.shortname)}" method="get">
<input accesskey="4" type="text" value="{$q}" name="q" size="20" />
<input type="submit" name="s" value="{trans 'Search'}" />
</form>
*}
{superblock}
</div>
{/block}

View File

@@ -0,0 +1,9 @@
{extends "idf/base.html"}
{block tabreview} class="active"{/block}
{block subtabs}
<div id="sub-tabs">
<a {if $inOpenReviews}class="active" {/if}href="{url 'IDF_Views_Review::index', array($project.shortname)}">{trans 'Open Reviews'}</a>
{if !$user.isAnonymous()} | <a {if $inCreate}class="active" {/if}href="{url 'IDF_Views_Review::create', array($project.shortname)}">{trans 'Start Code Review'}</a> {/if}
{superblock}
</div>
{/block}

View File

@@ -0,0 +1,69 @@
{extends "idf/review/base.html"}
{block docclass}yui-t3{assign $inCreate = true}{/block}
{block body}
{if $form.errors}
<div class="px-message-error">
<p>{trans 'The form contains some errors. Please correct them to submit the code review.'}</p>
{if $form.get_top_errors}
{$form.render_top_errors|unsafe}
{/if}
</div>
{/if}
<form method="post" enctype="multipart/form-data" action=".">
<table class="form" summary="">
<tr>
<th><strong>{$form.f.summary.labelTag}:</strong></th>
<td>{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if}
{$form.f.summary|unsafe}
</td>
</tr>
<tr>
<th><strong>{$form.f.description.labelTag}:</strong></th>
<td>{if $form.f.description.errors}{$form.f.description.fieldErrors}{/if}
{$form.f.description|unsafe}
</td>
</tr>
<tr>
<th><strong>{$form.f.commit.labelTag}:</strong></th>
<td>{if $form.f.commit.errors}{$form.f.commit.fieldErrors}{/if}
{$form.f.commit|unsafe}<br />
<span class="helptext">{trans 'Be sure to provide the right commit/revision reference for your patch to correctly apply.'}</span>
</td>
</tr>
<tr>
<th><strong>{$form.f.patch.labelTag}:</strong></th>
<td>{if $form.f.patch.errors}{$form.f.patch.fieldErrors}{/if}
{$form.f.patch|unsafe}
</td>
</tr>{if $isOwner or $isMember}
<tr>
<th><strong>{$form.f.status.labelTag}:</strong></th>
<td>{if $form.f.status.errors}{$form.f.status.fieldErrors}{/if}
{$form.f.status|unsafe}
</td>
</tr>{/if}
<tr>
<td>&nbsp;</td>
<td><input type="submit" value="{trans 'Start Code Review'}" name="submit" /> | <a href="{url 'IDF_Views_Review::index', array($project.shortname)}">{trans 'Cancel'}</a>
</td>
</tr>
</table>
</form>
{/block}
{block context}
<div class="issue-submit-info">
{blocktrans}<p>To start a code review, you need to provide:</p>
<ul>
<li>A commit or revision of the current code in the repository from which you started your work.</li>
<li>A patch describing your changes with respect to the reference commit.</li>
<li><strong>Check your patch to not provide any password or confidential information!</strong></li>
</ul>{/blocktrans}
</div>
{/block}
{block javascript}
<script type="text/javascript">
document.getElementById('id_summary').focus();
</script>{/block}

View File

@@ -0,0 +1,21 @@
{extends "idf/review/base.html"}
{block docclass}yui-t2{assign $inOpenReviews=true}{/block}
{block body}
{$reviews.render}
{if !$user.isAnonymous()}
{aurl 'url', 'IDF_Views_Review::create', array($project.shortname)}
<p><a href="{$url}"><img style="vertical-align: text-bottom;" src="{media '/idf/img/add.png'}" alt="+" align="bottom" /></a> <a href="{$url}">{trans 'New Code Review'}</a></p>{/if}
{/block}
{block context}
{*
{aurl 'open_url', 'IDF_Views_Issue::index', array($project.shortname)}
{aurl 'closed_url', 'IDF_Views_Issue::listStatus', array($project.shortname, 'closed')}
{blocktrans}<p><strong>Open issues:</strong> <a href="{$open_url}">{$open}</a></p>
<p><strong>Closed issues:</strong> <a href="{$closed_url}">{$closed}</a></p>{/blocktrans}
{assign $class = ''}{assign $i = 0}
<p class="smaller">{foreach $project.getTagCloud($cloud) as $label}
{aurl 'url', 'IDF_Views_Issue::listLabel', array($project.shortname, $label.id, 'open')}
{if $class != $label.class}{if $i != 0}<br />{/if}<strong class="label">{$label.class}:</strong> {/if}
<a href="{$url}" class="label">{$label.name}</a>,{assign $class = $label.class}{assign $i = $i + 1}{/foreach}</p>
*}{/block}

View File

@@ -0,0 +1,116 @@
{extends "idf/review/base-full.html"}
{block extraheader}<link rel="stylesheet" type="text/css" href="{media '/idf/css/prettify.css'}" />{/block}
{block docclass}yui-t1{assign $inCreate = true}{/block}
{block body}
{if $form.errors}
<div class="px-message-error">
<p>{trans 'The form contains some errors. Please correct them to submit your review.'}</p>
{if $form.get_top_errors}
{$form.render_top_errors|unsafe}
{/if}
</div>
{/if}
<table class="commit" summary="">
<tr>
<th><strong>{trans 'Created:'}</strong></th><td>{$patch.creation_dtime|date:"%Y-%m-%d %H:%M:%S"} ({$patch.creation_dtime|dateago})</td>
</tr>
<tr>
<th><strong>{trans 'Updated:'}</strong></th><td>{$review.modif_dtime|dateago}</td>
</tr>
<tr>
<th><strong>{trans 'Author:'}</strong></th><td>{$review.get_submitter()}</td>
</tr>
<tr>
<th><strong>{trans 'Commit:'}</strong></th><td class="mono"><a href="{url 'IDF_Views_Source::treeBase', array($project.shortname, $patch.get_commit().scm_id)}" title="{trans 'View corresponding source tree'}">{$patch.get_commit().scm_id}</a></td>
</tr>
<tr>
<th><strong>{trans 'Description:'}</strong></th><td>{issuetext $review.summary, $request}<br /><br />{issuetext $patch.summary, $request}</td>
</tr>
<tr>
<th><strong>{trans 'Reviewers:'}</strong></th><td>{if count($reviewers)}{foreach $reviewers as $r}{$r}, {/foreach}{else}{trans 'No reviewers at the moment.'}{/if}</td>
</tr>{if count($diff.files)}
<tr>
<th><strong>{trans 'Files:'}</strong></th>
<td>
{foreach $diff.files as $filename=>$diffdef}
{assign $ndiff = count($diffdef['chunks'])}
{assign $nc = $files[$filename][2]->count()}
<a href="{url 'IDF_Views_Source::tree', array($project.shortname, $patch.get_commit().scm_id, $filename)}">{$filename}</a> (<a href="#diff-{$filename|md5}">{blocktrans $ndiff}{$ndiff} diff{plural}{$ndiff} diffs{/blocktrans}</a>{if $nc}, <a href="#ct-{$filename|md5}">{blocktrans $nc}{$nc} comment{plural}{$nc} comments{/blocktrans}</a>{/if})<br />
{/foreach}
</td>
</tr>{/if}
<tr>{aurl 'url', 'IDF_Views_Review::getPatch', array($project.shortname, $patch.id)}
<th>&nbsp;</th><td><a href="{$url}"><img style="vertical-align: text-bottom;" src="{media '/idf/img/package-grey.png'}" alt="{trans 'Archive'}" align="bottom" /></a> <a href="{$url}" class="soft">{trans 'Download the corresponding diff file'}</a></td>
</tr>
</table>
{if !$user.isAnonymous()}
<div class="issue-submit-info" style="width: 50%">
<p><strong>{trans 'How to Participate in a Code Review'}</strong></p>
<p>{blocktrans}Code review is a process in which
after or before changes are commited into the code repository,
different people discuss the code changes. The goal is
to <strong>improve the quality of the code and the
contributions</strong>, as such, you must be pragmatic when writing
your review. Correctly mention the line numbers (in the old or in the
new file) and try to keep a good balance between seriousness and fun.
{/blocktrans}</p>
<p>{blocktrans}
<strong>Proposing code for review is intimidating</strong>, you know
you will receive critics, so please, as a reviewer, <strong>keep this
process fun</strong>, use it to help your contributor learn your
coding standards and the structure of the code and <strong>make them want
to propose more contributions</strong>.
{/blocktrans}</p></div>
{/if}
<form method="post" action=".">
{foreach $files as $file=>$def}
<table class="diff" summary=" ">
<tbody>
<tr id="diff-{$file|md5}"><th colspan="4">{$file}</th></tr>
<tr><th colspan="2">{trans 'Old'}</th><th colspan="2">{trans 'New'}</th></tr>
{$def[0]}
</tbody>
</table>
{assign $comments = $def[2]}
{assign $nc = $comments.count()}
{assign $i = 1}
{foreach $comments as $c}
<div class="issue-comment{if $i == 1} issue-comment-first{/if}{if $i == $nc} issue-comment-last{/if}" id="ic{$c.id}">{assign $who = $c.get_submitter()}{aurl 'whourl', 'IDF_Views_User::view', array($who.login)}
{aurl 'url', 'IDF_Views_Review::view', array($project.shortname, $review.id)}
{assign $id = $c.id}
{assign $url = $url~'#ic'~$c.id}
<p{if $i == 1} id="ct-{$file|md5}"{/if}>{blocktrans}Comment <a href="{$url}">{$i}</a> by <a href="{$whourl}">{$who}</a>, {$c.creation_dtime|date}{/blocktrans}</p>
<pre class="issue-comment-text">{issuetext $c.content, $request}</pre>
</div> {assign $i = $i + 1}
{/foreach}
{if !$user.isAnonymous()}
<table class="form" summary=" ">
<tr>
<td>&nbsp;</td>
<td>
<p>{blocktrans}Your comments on the changes in file <em>{$file}</em>:{/blocktrans}<br />{$def[1]|safe}</p>
</td>
</tr></table>{/if}
{/foreach}
{if !$user.isAnonymous()}
<table class="form" summary=" ">
<tr>
<td>&nbsp;</td>
<td><input type="submit" value="{trans 'Submit Code Review'}" name="submit" /> | <a href="{url 'IDF_Views_Review::index', array($project.shortname)}">{trans 'Cancel'}</a>
</td>
</tr></table>
{/if}
</form>
{/block}
u
{block javascript}
<script type="text/javascript" src="{media '/idf/js/prettify.js'}"></script>
<script type="text/javascript">
prettyPrint();
</script>
{/block}