"
+ end
+ end
+ end
+
+ class Formatter
+ def initialize(text)
+ @text = text
+ end
+
+ def to_html(*args)
+ html = formatter.render(@text)
+ # restore wiki links eg. [[Foo]]
+ html.gsub!(%r{\[(.*?)\]}) do
+ "[[#{$2}]]"
+ end
+ # restore Redmine links with double-quotes, eg. version:"1.0"
+ html.gsub!(/(\w):"(.+?)"/) do
+ "#{$1}:\"#{$2}\""
+ end
+ html
+ end
+
+ def get_section(index)
+ section = extract_sections(index)[1]
+ hash = Digest::MD5.hexdigest(section)
+ return section, hash
+ end
+
+ def update_section(index, update, hash=nil)
+ t = extract_sections(index)
+ if hash.present? && hash != Digest::MD5.hexdigest(t[1])
+ raise Redmine::WikiFormatting::StaleSectionError
+ end
+ t[1] = update unless t[1].blank?
+ t.reject(&:blank?).join "\n\n"
+ end
+
+ def extract_sections(index)
+ sections = ['', '', '']
+ offset = 0
+ i = 0
+ l = 1
+ inside_pre = false
+ @text.split(/(^(?:.+\r?\n\r?(?:\=+|\-+)|#+.+|~~~.*)\s*$)/).each do |part|
+ level = nil
+ if part =~ /\A~{3,}(\S+)?\s*$/
+ if $1
+ if !inside_pre
+ inside_pre = true
+ end
+ else
+ inside_pre = !inside_pre
+ end
+ elsif inside_pre
+ # nop
+ elsif part =~ /\A(#+).+/
+ level = $1.size
+ elsif part =~ /\A.+\r?\n\r?(\=+|\-+)\s*$/
+ level = $1.include?('=') ? 1 : 2
+ end
+ if level
+ i += 1
+ if offset == 0 && i == index
+ # entering the requested section
+ offset = 1
+ l = level
+ elsif offset == 1 && i > index && level <= l
+ # leaving the requested section
+ offset = 2
+ end
+ end
+ sections[offset] << part
+ end
+ sections.map(&:strip)
+ end
+
+ private
+
+ def formatter
+ @@formatter ||= Redcarpet::Markdown.new(
+ Redmine::WikiFormatting::Markdown::HTML.new(
+ :filter_html => true,
+ :hard_wrap => true
+ ),
+ :autolink => true,
+ :fenced_code_blocks => true,
+ :space_after_headers => true,
+ :tables => true,
+ :strikethrough => true,
+ :superscript => true
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/redmine/wiki_formatting/markdown/helper.rb b/lib/redmine/wiki_formatting/markdown/helper.rb
new file mode 100644
index 00000000..16f37c77
--- /dev/null
+++ b/lib/redmine/wiki_formatting/markdown/helper.rb
@@ -0,0 +1,45 @@
+# Redmine - project management software
+# Copyright (C) 2006-2014 Jean-Philippe Lang
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+module Redmine
+ module WikiFormatting
+ module Markdown
+ module Helper
+ def wikitoolbar_for(field_id)
+ heads_for_wiki_formatter
+ javascript_tag("var wikiToolbar = new jsToolBar(document.getElementById('#{field_id}')); wikiToolbar.draw();")
+ end
+
+ def initial_page_content(page)
+ "# #{@page.pretty_title}"
+ end
+
+ def heads_for_wiki_formatter
+ unless @heads_for_wiki_formatter_included
+ content_for :header_tags do
+ javascript_include_tag('jstoolbar/jstoolbar') +
+ javascript_include_tag('jstoolbar/markdown') +
+ javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language.to_s.downcase}") +
+ stylesheet_link_tag('jstoolbar')
+ end
+ @heads_for_wiki_formatter_included = true
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/plugins/redmine_code_review/GPL.txt b/plugins/redmine_code_review/GPL.txt
new file mode 100644
index 00000000..d511905c
--- /dev/null
+++ b/plugins/redmine_code_review/GPL.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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 2 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, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/plugins/redmine_code_review/README.rdoc b/plugins/redmine_code_review/README.rdoc
new file mode 100644
index 00000000..bd59da01
--- /dev/null
+++ b/plugins/redmine_code_review/README.rdoc
@@ -0,0 +1,35 @@
+= Redmine Code Review Plugin
+
+This is a plugin for Redmine which lets you annotate source code within the repository browser.
+
+http://www.r-labs.org/wiki/r-labs/Code_Review
+
+=== Plugin installation
+
+1. Copy the plugin directory into the plugins directory
+
+2. Migrate plugin:
+ rake redmine:plugins:migrate RAILS_ENV=production
+
+3. Start Redmine
+
+4. Add code review module into your project.
+
+5. Go to code review setting tab in the project setting page and select tracker.
+
+=== Language contributors
+
+* de.yml - Michael Diederich, Sebastian Bernhard
+* fr.yml - Thomas M
+* hu.yml - Péter Major
+* ko.yml - Ki-yong Kim, Ki Won Kim
+* nl.yml - Stefan Verstege
+* pt-br.yml - Alessandro Hecht
+* zh.yml - Marshall Wu
+* zh-tw.yml - Andrew Liu
+* ru.yml - Mykhaylo Sorochan
+* sk.yml - Milan Freml
+* es.yml - Ignacio Carrera
+* pl.yml - Rafal Grzymkowski
+* sv.yml - André Jonsson
+* bg.yml - Ivan Cenov, jwalkerbg
diff --git a/plugins/redmine_code_review/app/controllers/code_review_controller.rb b/plugins/redmine_code_review/app/controllers/code_review_controller.rb
new file mode 100644
index 00000000..33f5a203
--- /dev/null
+++ b/plugins/redmine_code_review/app/controllers/code_review_controller.rb
@@ -0,0 +1,398 @@
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2013 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+class CodeReviewController < ApplicationController
+ unloadable
+ before_filter :find_project, :authorize, :find_user, :find_setting, :find_repository
+
+ helper :sort
+ include SortHelper
+ helper :journals
+ helper :projects
+ include ProjectsHelper
+ helper :issues
+ include IssuesHelper
+ helper :code_review
+ include CodeReviewHelper
+ helper :custom_fields
+ include CustomFieldsHelper
+
+ def index
+ sort_init "#{Issue.table_name}.id", 'desc'
+ sort_update ["#{Issue.table_name}.id", "#{Issue.table_name}.status_id", "#{Issue.table_name}.subject", "path", "updated_at", "user_id", "#{Changeset.table_name}.committer", "#{Changeset.table_name}.revision"]
+
+ limit = per_page_option
+ @review_count = CodeReview.count(:conditions => ['project_id = ? and issue_id is NOT NULL', @project.id])
+ @all_review_count = CodeReview.count(:conditions => ['project_id = ?', @project.id])
+ @review_pages = Paginator.new self, @review_count, limit, params['page']
+ @show_closed = (params['show_closed'] == 'true')
+ show_closed_option = " and #{IssueStatus.table_name}.is_closed = ? "
+ if (@show_closed)
+ show_closed_option = ''
+ end
+ conditions = ["#{CodeReview.table_name}.project_id = ? and issue_id is NOT NULL" + show_closed_option, @project.id]
+ unless (@show_closed)
+ conditions << false
+ end
+
+ @reviews = CodeReview.order(sort_clause).limit(limit).where(conditions).joins(
+ "left join #{Change.table_name} on change_id = #{Change.table_name}.id left join #{Changeset.table_name} on #{Change.table_name}.changeset_id = #{Changeset.table_name}.id " +
+ "left join #{Issue.table_name} on issue_id = #{Issue.table_name}.id " +
+ "left join #{IssueStatus.table_name} on #{Issue.table_name}.status_id = #{IssueStatus.table_name}.id").offset(@review_pages.current.offset)
+ @i_am_member = @user.member_of?(@project)
+ render :template => 'code_review/index.html.erb', :layout => !request.xhr?
+ end
+
+ def new
+ begin
+ CodeReview.transaction {
+ @review = CodeReview.new
+ @review.issue = Issue.new
+
+ if params[:issue] and params[:issue][:tracker_id]
+ @review.issue.tracker_id = params[:issue][:tracker_id].to_i
+ else
+ @review.issue.tracker_id = @setting.tracker_id
+ end
+ @review.safe_attributes = params[:review]
+ @review.project_id = @project.id
+ @review.issue.project_id = @project.id
+
+ @review.user_id = @user.id
+ @review.updated_by_id = @user.id
+ @review.issue.start_date = Date.today
+ @review.action_type = params[:action_type]
+ @review.rev = params[:rev] unless params[:rev].blank?
+ @review.rev_to = params[:rev_to] unless params[:rev_to].blank?
+ @review.file_path = params[:path] unless params[:path].blank?
+ @review.file_count = params[:file_count].to_i unless params[:file_count].blank?
+ @review.attachment_id = params[:attachment_id].to_i unless params[:attachment_id].blank?
+ @issue = @review.issue
+ @review.issue.safe_attributes = params[:issue] unless params[:issue].blank?
+ @review.diff_all = (params[:diff_all] == 'true')
+
+ @parent_candidate = get_parent_candidate(@review.rev) if @review.rev
+
+ if request.post?
+ @review.issue.save!
+ if @review.changeset
+ @review.changeset.issues.each {|issue|
+ create_relation @review, issue, @setting.issue_relation_type
+ } if @setting.auto_relation?
+ elsif @review.attachment and @review.attachment.container_type == 'Issue'
+ issue = Issue.find_by_id(@review.attachment.container_id)
+ create_relation @review, issue, @setting.issue_relation_type if @setting.auto_relation?
+ end
+ @review.open_assignment_issues(@user.id).each {|issue|
+ create_relation @review, issue, IssueRelation::TYPE_RELATES
+ watcher = Watcher.new
+ watcher.watchable_id = @review.issue.id
+ watcher.watchable_type = 'Issue'
+ watcher.user = issue.author
+ watcher.save!
+ }
+ @review.save!
+
+ render :partial => 'add_success', :status => 200
+ return
+ else
+ change_id = params[:change_id].to_i unless params[:change_id].blank?
+ @review.change = Change.find(change_id) if change_id
+ @review.line = params[:line].to_i unless params[:line].blank?
+ if (@review.changeset and @review.changeset.user_id)
+ @review.issue.assigned_to_id = @review.changeset.user_id
+ end
+ @default_version_id = @review.issue.fixed_version.id if @review.issue.fixed_version
+ if @review.changeset and @default_version_id.blank?
+ @review.changeset.issues.each {|issue|
+ if issue.fixed_version
+ @default_version_id = issue.fixed_version.id
+ break;
+ end
+ }
+ end
+ @review.open_assignment_issues(@user.id).each {|issue|
+ if issue.fixed_version
+ @default_version_id = issue.fixed_version.id
+ break;
+ end
+ } unless @default_version_id
+
+
+ end
+ render :partial => 'new_form', :status => 200
+ }
+ rescue ActiveRecord::RecordInvalid
+ render :partial => 'new_form', :status => 200
+ end
+ end
+
+ def assign
+ code = {}
+ code[:action_type] = params[:action_type] unless params[:action_type].blank?
+ code[:rev] = params[:rev] unless params[:rev].blank?
+ code[:rev_to] = params[:rev_to] unless params[:rev_to].blank?
+ code[:path] = params[:path] unless params[:path].blank?
+ code[:change_id] = params[:change_id].to_i unless params[:change_id].blank?
+ code[:changeset_id] = params[:changeset_id].to_i unless params[:changeset_id].blank?
+ code[:attachment_id] = params[:attachment_id].to_i unless params[:attachment_id].blank?
+ code[:repository_id] = @repository_id if @repository_id
+
+ changeset = Changeset.find(code[:changeset_id]) if code[:changeset_id]
+ if (changeset == nil and code[:change_id] != nil)
+ change = Change.find(code[:change_id])
+ changeset = change.changeset if change
+ end
+ attachment = Attachment.find(code[:attachment_id]) if code[:attachment_id]
+
+ issue = {}
+ issue[:subject] = l(:code_review_requrest)
+ issue[:subject] << " [#{changeset.text_tag}: #{changeset.short_comments}]" if changeset
+ unless changeset
+ issue[:subject] << " [#{attachment.filename}]" if attachment
+ end
+ issue[:tracker_id] = @setting.assignment_tracker_id if @setting.assignment_tracker_id
+
+ redirect_to :controller => 'issues', :action => "new" , :project_id => @project,
+ :issue => issue, :code => code
+ end
+
+ def update_diff_view
+ @show_review_id = params[:review_id].to_i unless params[:review_id].blank?
+ @show_review = CodeReview.find(@show_review_id) if @show_review_id
+ @review = CodeReview.new
+ @rev = params[:rev] unless params[:rev].blank?
+ @rev_to = params[:rev_to] unless params[:rev_to].blank?
+ @path = params[:path] unless params[:path].blank?
+ @paths = []
+ @paths << @path unless @path.blank?
+
+ @action_type = params[:action_type]
+ changeset = @repository.find_changeset_by_name(@rev)
+ if @paths.empty?
+ changeset.filechanges.each{|chg|
+ }
+ end
+
+ url = @repository.url
+ root_url = @repository.root_url
+ if (url == nil || root_url == nil)
+ fullpath = @path
+ else
+ rootpath = url[root_url.length, url.length - root_url.length]
+ if rootpath.blank?
+ fullpath = @path
+ else
+ fullpath = (rootpath + '/' + @path).gsub(/[\/]+/, '/')
+ end
+ end
+ @change = nil
+ changeset.filechanges.each{|chg|
+ @change = chg if ((chg.path == fullpath) or ("/#{chg.path}" == fullpath)) or (chg.path == "/#{@path}")
+ } unless @path.blank?
+
+ @changeset = changeset
+ if @path
+ @reviews = CodeReview.where(['file_path = ? and rev = ? and issue_id is NOT NULL', @path, @rev]).all
+ else
+ @reviews = CodeReview.where(['rev = ? and issue_id is NOT NULL', @rev]).all
+ end
+ @review.change_id = @change.id if @change
+
+ #render :partial => 'show_error'
+ #return
+
+
+
+ render :partial => 'update_diff_view'
+ end
+
+ def update_attachment_view
+ @show_review_id = params[:review_id].to_i unless params[:review_id].blank?
+ @attachment_id = params[:attachment_id].to_i
+ @show_review = CodeReview.find(@show_review_id) if @show_review_id
+ @review = CodeReview.new
+ @action_type = 'attachment'
+ @attachment = Attachment.find(@attachment_id)
+
+ @reviews = CodeReview.where(['attachment_id = (?) and issue_id is NOT NULL', @attachment_id]).all
+
+ render :partial => 'update_diff_view'
+ end
+
+ def show
+ @review = CodeReview.find(params[:review_id].to_i) unless params[:review_id].blank?
+ @repository = @review.repository if @review
+ @assignment = CodeReviewAssignment.find(params[:assignment_id].to_i) unless params[:assignment_id].blank?
+ @repository_id = @assignment.repository_identifier if @assignment
+ @issue = @review.issue if @review
+ @allowed_statuses = @review.issue.new_statuses_allowed_to(User.current) if @review
+ target = @review if @review
+ target = @assignment if @assignment
+ @repository_id = target.repository_identifier
+ if request.xhr? or !params[:update].blank?
+ render :partial => 'show'
+ elsif target.path
+ #@review = @review.root
+ path = URI.decode(target.path)
+ #path = '/' + path unless path.match(/^\//)
+ action_name = target.action_type
+ rev_to = ''
+ rev_to = '&rev_to=' + target.rev_to if target.rev_to
+ if action_name == 'attachment'
+ attachment = target.attachment
+ url = url_for(:controller => 'attachments', :action => 'show', :id => attachment.id) + '/' + URI.escape(attachment.filename)
+ url << '?review_id=' + @review.id.to_s if @review
+ redirect_to(url)
+ else
+ path = nil if target.diff_all
+ url = url_for(:controller => 'repositories', :action => action_name, :id => @project,
+ :repository_id => @repository_id, :rev => target.revision, :path => path)
+ #url = url_for(:controller => 'repositories', :action => action_name, :id => @project, :repository_id => @repository_id) + path + '?rev=' + target.revision
+ url << '?review_id=' + @review.id.to_s + rev_to if @review
+ redirect_to url
+ end
+ end
+ end
+
+ def reply
+ begin
+ @review = CodeReview.find(params[:review_id].to_i)
+ @issue = @review.issue
+ @issue.lock_version = params[:issue][:lock_version]
+ comment = params[:reply][:comment]
+ journal = @issue.init_journal(User.current, comment)
+ @review.safe_attributes = params[:review]
+ @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
+
+ @issue.save!
+ if !journal.new_record?
+ # Only send notification if something was actually changed
+ flash[:notice] = l(:notice_successful_update)
+ end
+
+ render :partial => 'show'
+ rescue ActiveRecord::StaleObjectError
+ # Optimistic locking exception
+ @error = l(:notice_locking_conflict)
+ render :partial => 'show'
+ end
+ end
+
+ def update
+ begin
+ CodeReview.transaction {
+ @review = CodeReview.find(params[:review_id].to_i)
+ journal = @review.issue.init_journal(User.current, nil)
+ @allowed_statuses = @review.issue.new_statuses_allowed_to(User.current)
+ @issue = @review.issue
+ @issue.lock_version = params[:issue][:lock_version]
+ @review.safe_attributes = params[:review]
+ @review.updated_by_id = @user.id
+ @review.save!
+ @review.issue.save!
+ @notice = l(:notice_review_updated)
+ lang = current_language
+ Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
+ set_language lang if respond_to? 'set_language'
+ render :partial => 'show'
+ }
+ rescue ActiveRecord::StaleObjectError
+ # Optimistic locking exception
+ @error = l(:notice_locking_conflict)
+ render :partial => 'show'
+ rescue
+ render :partial => 'show'
+ end
+ end
+
+
+ def destroy
+ @review = CodeReview.find(params[:review_id].to_i)
+ @review.issue.destroy if @review
+ render :text => 'delete success.'
+ end
+
+ def forward_to_revision
+ path = params[:path]
+ rev = params[:rev]
+ changesets = @repository.latest_changesets(path, rev, Setting.repository_log_display_limit.to_i)
+ change = changesets[0]
+
+ identifier = change.identifier
+ redirect_to url_for(:controller => 'repositories', :action => 'entry', :id => @project, :repository_id => @repository_id) + '/' + path + '?rev=' + identifier.to_s
+
+ end
+
+ def preview
+ @text = params[:review][:comment]
+ @text = params[:reply][:comment] unless @text
+ render :partial => 'common/preview'
+ end
+
+ def update_revisions_view
+ changeset_ids = []
+ #changeset_ids = CGI.unescape(params[:changeset_ids]).split(',') unless params[:changeset_ids].blank?
+ changeset_ids = params[:changeset_ids].split(',') unless params[:changeset_ids].blank?
+ @changesets = []
+ changeset_ids.each {|id|
+ @changesets << @repository.find_changeset_by_name(id) unless id.blank?
+ }
+ render :partial => 'update_revisions'
+ end
+
+ private
+ def find_repository
+ if params[:repository_id].present? and @project.repositories
+ @repository = @project.repositories.find_by_identifier_param(params[:repository_id])
+ else
+ @repository = @project.repository
+ end
+ @repository_id = @repository.identifier_param if @repository.respond_to?("identifier_param")
+ end
+
+ def find_project
+ # @project variable must be set before calling the authorize filter
+ @project = Project.find(params[:id])
+ end
+
+ def find_user
+ @user = User.current
+ end
+
+
+ def find_setting
+ @setting = CodeReviewProjectSetting.find_or_create(@project)
+ end
+
+ def get_parent_candidate(revision)
+ changeset = @repository.find_changeset_by_name(revision)
+ changeset.issues.each {|issue|
+ return Issue.find(issue.parent_issue_id) if issue.parent_issue_id
+ }
+ nil
+ end
+
+ def create_relation(review, issue, type)
+ return unless issue.project == @project
+ relation = IssueRelation.new
+ relation.relation_type = type
+ relation.issue_from_id = review.issue.id
+ relation.issue_to_id = issue.id
+ relation.save!
+ end
+end
diff --git a/plugins/redmine_code_review/app/controllers/code_review_settings_controller.rb b/plugins/redmine_code_review/app/controllers/code_review_settings_controller.rb
new file mode 100644
index 00000000..1f0464dd
--- /dev/null
+++ b/plugins/redmine_code_review/app/controllers/code_review_settings_controller.rb
@@ -0,0 +1,119 @@
+# Code Review plugin for Redmine
+# Copyright (C) 2010 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+class CodeReviewSettingsController < ApplicationController
+ unloadable
+ layout 'base'
+ menu_item :code_review
+ include CodeReviewAutoAssignSettings
+
+ before_filter :find_project, :authorize, :find_user
+
+ def update
+ begin
+ @setting = CodeReviewProjectSetting.find_or_create(@project)
+
+ @setting.safe_attributes = params[:setting]
+ @setting.updated_by = @user.id
+ params[:auto_assign][:filters] = params[:auto_assign][:filters].values unless params[:auto_assign][:filters].blank?
+ @setting.auto_assign_settings = params[:auto_assign].to_yaml
+
+ @setting.save!
+
+ flash[:notice] = l(:notice_successful_update)
+ rescue ActiveRecord::StaleObjectError
+ # Optimistic locking exception
+ flash[:error] = l(:notice_locking_conflict)
+ end
+ redirect_to :controller => 'projects', :action => "settings", :id => @project, :tab => 'code_review'
+
+ end
+
+ def add_filter
+ setting = CodeReviewProjectSetting.find_or_create(@project)
+ @auto_assign = setting.auto_assign_settings
+ filters = params[:auto_assign][:filters].values unless params[:auto_assign][:filters].blank?
+ filters = [] unless filters
+ filters << params[:auto_assign_add_filter]
+
+ @auto_assign.filters = filters.collect{|f|
+ filter = AssignmentFilter.new
+ filter.attributes = f
+ filter
+ }
+ @auto_assign.filter_enabled = true
+ render :partial => "code_review_settings/filters"
+ end
+
+ def edit_filter
+ setting = CodeReviewProjectSetting.find_or_create(@project)
+ @auto_assign = setting.auto_assign_settings
+ num = params[:num].to_i
+ filters = params[:auto_assign][:filters].values unless params[:auto_assign][:filters].blank?
+ filters = [] unless filters
+ i = 0
+ @auto_assign.filters = filters.collect{|f|
+ filter = AssignmentFilter.new
+ if i == num
+ filter.attributes = params[:auto_assign_edit_filter][num.to_s]
+ else
+ filter.attributes = f
+ end
+ i = i + 1
+ filter
+ }
+ render :partial => "code_review_settings/filters"
+ end
+
+ def sort
+ setting = CodeReviewProjectSetting.find_or_create(@project)
+ @auto_assign = setting.auto_assign_settings
+ filters = params[:auto_assign][:filters].values unless params[:auto_assign][:filters].blank?
+ filters = [] unless filters
+ num = params[:auto_assign_filter][:num].to_i
+ move_to = params[:auto_assign_filter][:move_to]
+
+ if move_to == 'highest'
+ filters[num][:order] = 0
+ elsif move_to == 'higher'
+ filters[num][:order] = filters[num][:order].to_i - 15
+ elsif move_to == 'lower'
+ filters[num][:order] = filters[num][:order].to_i + 15
+ elsif move_to == 'lowest'
+ filters[num][:order] = 999999999
+ end
+
+ @auto_assign.filters = filters.collect{|f|
+ filter = AssignmentFilter.new
+ filter.attributes = f
+ filter
+ }
+
+
+ render :partial => "code_review_settings/filters"
+ end
+ private
+ def find_project
+ # @project variable must be set before calling the authorize filter
+ @project = Project.find(params[:id])
+ end
+
+ def find_user
+ @user = User.current
+ end
+
+end
diff --git a/plugins/redmine_code_review/app/helpers/code_review_helper.rb b/plugins/redmine_code_review/app/helpers/code_review_helper.rb
new file mode 100644
index 00000000..2086c33e
--- /dev/null
+++ b/plugins/redmine_code_review/app/helpers/code_review_helper.rb
@@ -0,0 +1,37 @@
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2011 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+module CodeReviewHelper
+ unloadable
+ def show_assignments(assignments, project, options = {})
+ html = "#{l(:review_assignments)}:"
+ assignments.each do |assignment|
+ issue = assignment.issue
+ html << link_to("##{issue.id} ", {:controller => 'issues', :action => 'show', :id => issue.id},
+ :class => issue.css_classes, :title => "#{issue}(#{issue.status})")
+ end if assignments
+
+ link = link_to(l(:button_add), {:controller => 'code_review',
+ :action => 'assign', :id=>project, :action_type => options[:action_type],
+ :rev => options[:rev], :rev_to => options[:rev_to], :path => options[:path],
+ :change_id => options[:change_id], :attachment_id => options[:attachment_id],
+ :changeset_id => options[:changeset_id]}, :class => 'icon icon-add')
+
+ html << link if link
+
+ html
+ end
+end
diff --git a/plugins/redmine_code_review/app/models/code_review.rb b/plugins/redmine_code_review/app/models/code_review.rb
new file mode 100644
index 00000000..0c5e986a
--- /dev/null
+++ b/plugins/redmine_code_review/app/models/code_review.rb
@@ -0,0 +1,175 @@
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2012 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+class CodeReview < ActiveRecord::Base
+ include Redmine::SafeAttributes
+ unloadable
+ belongs_to :project
+ belongs_to :change
+ belongs_to :issue
+ belongs_to :updated_by, :class_name => 'User', :foreign_key => 'updated_by_id'
+ belongs_to :attachment
+
+ validates_presence_of :project_id, :user_id, :updated_by_id, :issue,
+ :subject, :action_type, :line
+
+ STATUS_OPEN = 0
+ STATUS_CLOSED = 1
+
+ safe_attributes 'change_id', 'subject', 'line', 'parent_id', 'comment', 'status_id'
+
+ def before_create
+ issue = Issue.new unless issue
+ end
+
+ def is_closed?
+ issue.closed?
+ #self.root.status == STATUS_CLOSED
+ end
+
+ def close
+ issue.status = IssueStatus.find(5)
+ #self.root.status = STATUS_CLOSED
+ end
+
+ def reopen
+ issue.status = IssueStatus.find(1)
+ #self.root.status = STATUS_OPEN
+ end
+
+ def committer
+ return changeset.author if changeset
+ end
+
+ def path
+ begin
+ return file_path if file_path
+ return @path if @path
+ if attachment_id
+ @path = attachment.filename
+ return @path
+ end
+ repository = changeset.repository
+ url = repository.url
+ root_url = repository.root_url
+ if (url == nil || root_url == nil)
+ @path = change.path
+ return @path
+ end
+ rootpath = url[root_url.length, url.length - root_url.length]
+ if rootpath == '/' || rootpath.blank?
+ @path = change.path
+ else
+ @path = change.path[rootpath.length, change.path.length - rootpath.length]
+ end
+ rescue => ex
+ return ex.to_s
+ end
+ end
+
+ def revision
+ return rev if rev
+ changeset.revision if changeset
+ end
+
+ def changeset
+ @changeset ||= change.changeset if change
+ end
+
+ def repository
+ @repository ||= changeset.repository if changeset
+ end
+
+ def repository_identifier
+ return nil unless repository
+ @repository_identifier ||= repository.identifier_param
+ end
+
+ def comment=(str)
+ issue.description = str if issue
+ end
+
+ def comment
+ issue.description if issue
+ end
+
+ def before_save
+ issue.project_id = project_id unless issue.project_id
+ end
+
+ def validate
+ unless issue.validate
+ false
+
+ end
+ end
+
+ def user=(u)
+ issue.author = u
+ end
+
+ def user_id=(id)
+ issue.author_id = id
+ end
+
+ def user_id
+ issue.author_id
+ end
+
+ def user
+ issue.author if issue
+ end
+
+ def subject=(s)
+ issue.subject = s
+ end
+
+ def subject
+ issue.subject
+ end
+
+ def parent_id= (p)
+ issue.parent_issue_id = p
+ end
+
+ def parent_id
+ issue.parent_issue_id
+ end
+
+ def status_id=(s)
+ issue.status_id = s
+ end
+
+ def status_id
+ issue.status_id
+ end
+
+ def open_assignment_issues(user_id)
+ issues = []
+ assignments = []
+ assignments = change.code_review_assignments if change
+ assignments = assignments + changeset.code_review_assignments if changeset
+ assignments = assignments + attachment.code_review_assignments if attachment
+
+ assignments.each {|assignment|
+ unless assignment.is_closed?
+ issues << assignment.issue if user_id == assignment.issue.assigned_to_id
+ end
+ }
+
+ issues
+ end
+end
diff --git a/plugins/redmine_code_review/app/models/code_review_assignment.rb b/plugins/redmine_code_review/app/models/code_review_assignment.rb
new file mode 100644
index 00000000..75c45e16
--- /dev/null
+++ b/plugins/redmine_code_review/app/models/code_review_assignment.rb
@@ -0,0 +1,80 @@
+# Code Review plugin for Redmine
+# Copyright (C) 2010-2011 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+class CodeReviewAssignment < ActiveRecord::Base
+ unloadable
+ belongs_to :issue
+ belongs_to :change
+ belongs_to :changeset
+ belongs_to :attachment
+ validates_presence_of :issue_id
+
+ def is_closed?
+ issue.closed?
+ end
+
+ def path
+ file_path
+ end
+
+ def revision
+ return rev if rev
+ changeset.revision if changeset
+ end
+
+ def repository
+ @repository ||= change.changeset.repository if change
+ @repository ||= changeset.repository if changeset
+ @repository
+ end
+
+ def repository_identifier
+ return nil unless repository
+ @repository_identifier ||= repository.identifier_param if repository.respond_to?("identifier_param")
+ end
+
+ def self.create_with_changeset(changeset)
+ project = changeset.project
+ setting = CodeReviewProjectSetting.find_or_create(project)
+ auto_assign = setting.auto_assign_settings
+ assignment = CodeReviewAssignment.new
+ issue = Issue.new
+ issue.subject = auto_assign.subject
+ issue.subject = l(:code_review_requrest) if issue.subject.blank?
+ issue.subject = issue.subject.sub("$REV" , changeset.revision)
+ issue.subject = issue.subject.sub("$COMMENTS" , changeset.comments.split(//u)[0..60].join) unless changeset.comments.blank?
+ issue.tracker_id = setting.assignment_tracker_id
+ issue.project = project
+ issue.author = User.find(auto_assign.author_id)
+ issue.assigned_to_id = auto_assign.select_assign_to(project, changeset.user)
+ issue.description = auto_assign.description
+ issue.description = issue.description.sub("$REV" , changeset.revision) unless issue.description.blank?
+ issue.description = issue.description.sub("$COMMENTS" , changeset.comments) unless changeset.comments.blank?
+
+ issue.save!
+
+ assignment.issue_id = issue.id
+ assignment.changeset_id = changeset.id
+ assignment.save!
+ assignment
+ end
+
+
+ def diff_all
+ path.blank?
+ end
+end
diff --git a/plugins/redmine_code_review/app/models/code_review_project_setting.rb b/plugins/redmine_code_review/app/models/code_review_project_setting.rb
new file mode 100644
index 00000000..aa69ae69
--- /dev/null
+++ b/plugins/redmine_code_review/app/models/code_review_project_setting.rb
@@ -0,0 +1,77 @@
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2011 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+class CodeReviewProjectSetting < ActiveRecord::Base
+ unloadable
+ include Redmine::SafeAttributes
+ include CodeReviewAutoAssignSettings
+
+ belongs_to :project
+ belongs_to :tracker
+ belongs_to :assignment_tracker, :class_name => 'Tracker'
+
+ validates_presence_of :project_id
+ validates_presence_of :tracker_id
+ validates_presence_of :assignment_tracker_id
+
+ before_save :set_assignment_settings
+
+ safe_attributes 'tracker_id', 'assignment_tracker_id', 'hide_code_review_tab', 'auto_relation', 'tracker_in_review_dialog'
+
+ AUTORELATION_TYPE_NONE = 0
+ AUTORELATION_TYPE_RELATES = 1
+ AUTORELATION_TYPE_BLOCKS = 2
+
+ def self.find_or_create(project)
+ setting = CodeReviewProjectSetting.find_by_project_id(project.id)
+ unless setting
+ setting = CodeReviewProjectSetting.new
+ setting.project_id = project.id
+ return setting if project.trackers.length == 0
+ setting.tracker = project.trackers[0]
+ setting.assignment_tracker = project.trackers[0]
+ setting.save!
+ end
+ setting
+ end
+
+ def auto_assign_settings
+ @auto_assign_settings ||= AutoAssignSettings.load(auto_assign)
+ end
+
+ def auto_assign_settings=(settings)
+ @auto_assign_settings = settings
+ end
+
+ def issue_relation_type
+ return IssueRelation::TYPE_RELATES if auto_relation == CodeReviewProjectSetting::AUTORELATION_TYPE_RELATES
+ return IssueRelation::TYPE_BLOCKS if auto_relation == CodeReviewProjectSetting::AUTORELATION_TYPE_BLOCKS
+ return nil
+ end
+
+ def auto_relation?
+ issue_relation_type != nil
+ end
+
+ private
+ def set_assignment_settings
+ if auto_assign_settings
+ self.auto_assign = auto_assign_settings.to_s
+ else
+ self.auto_assign = nil
+ end
+ end
+end
diff --git a/plugins/redmine_code_review/app/models/code_review_user_setting.rb b/plugins/redmine_code_review/app/models/code_review_user_setting.rb
new file mode 100644
index 00000000..f4058ad6
--- /dev/null
+++ b/plugins/redmine_code_review/app/models/code_review_user_setting.rb
@@ -0,0 +1,50 @@
+# Code Review plugin for Redmine
+# Copyright (C) 2011 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+class CodeReviewUserSetting < ActiveRecord::Base
+ unloadable
+ belongs_to :user
+
+ validates_presence_of :user_id
+ validates_presence_of :mail_notification
+ validates_uniqueness_of :user_id
+
+ NOTIFCIATION_NONE = 0
+ NOTIFICATION_INVOLVED_IN = 1
+ NOTIFICATION_ALL = 2
+
+ def CodeReviewUserSetting.find_or_create(uid)
+ setting = CodeReviewUserSetting.find_by_user_id(uid)
+ return setting if setting
+ setting = CodeReviewUserSetting.new
+ setting.user_id = uid
+ setting.mail_notification = NOTIFICATION_INVOLVED_IN
+ setting.save
+ return setting
+ end
+
+ def mail_notification_none?
+ mail_notification == NOTIFCIATION_NONE
+ end
+
+ def mail_notification_involved_in?
+ mail_notification == NOTIFICATION_INVOLVED_IN
+ end
+
+ def mail_notification_all?
+ mail_notification == NOTIFICATION_ALL
+ end
+end
diff --git a/plugins/redmine_code_review/app/models/review_mailer.rb b/plugins/redmine_code_review/app/models/review_mailer.rb
new file mode 100644
index 00000000..3975f9bb
--- /dev/null
+++ b/plugins/redmine_code_review/app/models/review_mailer.rb
@@ -0,0 +1,122 @@
+# Code Review plugin for Redmine
+# Copyright (C) 2009 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+class ReviewMailer < Mailer
+
+ def review_add(project, review)
+ redmine_headers 'Project' => review.project.identifier,
+ 'Review-Id' => review.id,
+ 'Review-Author' => review.user.login
+
+ recipients get_mail_addresses(review)
+
+ subject "[#{review.project.name} - #{l(:label_review_new)} - #{l(:label_review)}##{review.id}] "
+ review_url = url_for(:controller => 'code_review', :action => 'show', :id => project, :review_id => review.id)
+
+ body :review => review, :review_url => review_url
+
+ return if (l(:this_is_checking_for_before_rails_2_2_2) == 'this_is_checking_for_before_rails_2_2_2')
+ # 何故かrails 2.2 以後は以下の処理が必要
+
+ content_type "multipart/alternative"
+
+ part "text/plain" do |p|
+ p.body = render_message("review_add.text.plain.erb", :body => body, :review=>review, :review_url => review_url)
+ end
+
+ part "text/html" do |p|
+ p.body = render_message("review_add.text.html.erb", :body => body, :review=>review, :review_url => review_url)
+ end
+ end
+
+ def review_reply(project, review)
+ redmine_headers 'Project' => review.project.identifier,
+ 'Review-Id' => review.id,
+ 'Review-Author' => review.user.login
+
+ recipients recipients get_mail_addresses(review)
+
+ subject "[#{review.project.name} - Updated - #{l(:label_review)}##{review.root.id}] "
+ review_url = url_for(:controller => 'code_review', :action => 'show', :id => project, :review_id => review.root.id)
+ body :review => review, :review_url => review_url
+
+ return if (l(:this_is_checking_for_before_rails_2_2_2) == 'this_is_checking_for_before_rails_2_2_2')
+ # 何故かrails 2.2 以後は以下の処理が必要
+
+ content_type "multipart/alternative"
+
+ part "text/plain" do |p|
+ p.body = render_message("review_reply.text.plain.erb", :body => body, :review=>review, :review_url => review_url)
+ end
+
+ part "text/html" do |p|
+ p.body = render_message("review_reply.text.html.erb", :body => body, :review=>review, :review_url => review_url)
+ end
+
+ end
+
+ def review_status_changed(project, review)
+ redmine_headers 'Project' => review.project.identifier,
+ 'Review-Id' => review.id,
+ 'Review-Author' => review.user.login
+
+ recipients recipients get_mail_addresses(review)
+
+ new_status = l(:label_review_open) if review.status_changed_to == CodeReview::STATUS_OPEN
+ new_status = l(:label_review_closed) if review.status_changed_to == CodeReview::STATUS_CLOSED
+
+ subject "[#{review.project.name} - Updated - #{l(:label_review)}##{review.root.id}] Status changed to #{new_status}."
+ review_url = url_for(:controller => 'code_review', :action => 'show', :id => project, :review_id => review.root.id)
+
+ body :review => review, :review_url => review_url
+
+ return if (l(:this_is_checking_for_before_rails_2_2_2) == 'this_is_checking_for_before_rails_2_2_2')
+ # 何故かrails 2.2 以後は以下の処理が必要
+
+ content_type "multipart/alternative"
+
+ part "text/plain" do |p|
+ p.body = render_message("review_status_changed.text.plain.erb", :body => body, :review=>review, :review_url => review_url)
+ end
+
+ part "text/html" do |p|
+ p.body = render_message("review_status_changed.text.html.erb", :body => body, :review=>review, :review_url => review_url)
+ end
+ end
+
+ def get_mail_addresses(review)
+ mail_addresses = []
+ review.root.users_for_notification.each{|u|
+ mail_addresses << u.mail
+ }
+ committer = review.change.changeset.user
+ if committer
+ setting = CodeReviewUserSetting.find_or_create(committer.id)
+ mail_addresses << committer.mail if setting and !setting.mail_notification_none?
+ end
+
+ review.project.members.each{|member|
+ user = member.user
+ setting = CodeReviewUserSetting.find_or_create(user.id)
+ next unless setting
+ mail_addresses << user.mail if setting.mail_notification_all?
+ }
+ mail_addresses.compact.uniq
+
+ end
+
+end
diff --git a/plugins/redmine_code_review/app/views/code_review/_add_success.html.erb b/plugins/redmine_code_review/app/views/code_review/_add_success.html.erb
new file mode 100644
index 00000000..ba46d153
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_add_success.html.erb
@@ -0,0 +1,27 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2009 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+<%= javascript_tag do %>
+
+var line = <%= @review.line %>;
+var review_id = <%= @review.id %>;
+var file_count = <%= @review.file_count %>;
+hideForm();
+setShowReviewButton(line, review_id, false, file_count);
+
+<% end %>
\ No newline at end of file
diff --git a/plugins/redmine_code_review/app/views/code_review/_body_bottom.html.erb b/plugins/redmine_code_review/app/views/code_review/_body_bottom.html.erb
new file mode 100644
index 00000000..6c295f17
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_body_bottom.html.erb
@@ -0,0 +1,82 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2010 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+
+<%
+is_target = false
+
+if project and controller and project.module_enabled?(:code_review)
+ is_target = true
+ is_target = false unless User.current.allowed_to?({:controller => 'code_review', :action => 'update_diff_view'}, project)
+ setting = CodeReviewProjectSetting.find(:first, :conditions => ['project_id = ?', project.id])
+ is_target = false unless setting
+ is_target = false if(setting && setting.tracker_id == nil)
+ action_name = controller.action_name
+ is_target = false unless action_name
+ is_target = false unless (controller.class.name == 'RepositoriesController' or controller.class.name == 'AttachmentsController')
+ if (is_target == true)
+ context = {:project => project, :controller => controller, :requrest => request}
+ %>
+ <% if (controller.class.name == 'AttachmentsController') %>
+ <%= render :partial => 'code_review/change_attachement_view', :locals => context %>
+ <% elsif (action_name == 'show' or action_name == 'revisions') %>
+ <%= render :partial => 'code_review/change_repository_view', :locals => context %>
+ <% elsif (action_name == 'revision') %>
+ <%= render :partial => 'code_review/change_revision_view', :locals => context %>
+ <% elsif (action_name == 'diff' or action_name == 'entry' or action_name == 'annotate')%>
+ <%if (controller.params[:rev].blank? or controller.params[:rev] == 'master')%>
+ <%= render :partial => 'code_review/change_entry_norevision_view', :locals => context %>
+ <% else
+ changeset = @repository.find_changeset_by_name(controller.params[:rev])
+ %>
+ <% unless changeset %>
+ <%= render :partial => 'code_review/change_entry_norevision_view', :locals => context %>
+ <% else
+ parameters = request.parameters
+ rev_to = parameters['rev_to'] unless parameters['rev_to'].blank?
+ review_id = parameters['review_id']
+ rev = parameters['rev']
+ path = parameters['path']
+
+
+ repository_id = @repository.identifier_param if @repository.respond_to?("identifier_param")
+ url = url_for :controller => 'code_review', :action => 'update_diff_view', :id => project, :repository_id => repository_id
+ %>
+
+
+
+ <% end %>
+
+ <% end %>
+ <% end %>
+ <%
+ end
+end
+-%>
+
+
+
diff --git a/plugins/redmine_code_review/app/views/code_review/_change_attachement_view.html.erb b/plugins/redmine_code_review/app/views/code_review/_change_attachement_view.html.erb
new file mode 100644
index 00000000..afaed4c7
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_change_attachement_view.html.erb
@@ -0,0 +1,35 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2010-2012 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+<%
+parameters = request.parameters
+id = parameters[:id].to_i
+attachment = Attachment.find(id)
+return '' unless attachment.is_text? or attachment.is_diff?
+review_id = parameters[:review_id] unless parameters[:review_id].blank?
+url = url_for :controller => 'code_review', :action => 'update_attachment_view', :id => project
+-%>
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/redmine_code_review/app/views/code_review/_change_entry_norevision_view.html.erb b/plugins/redmine_code_review/app/views/code_review/_change_entry_norevision_view.html.erb
new file mode 100644
index 00000000..096a1a47
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_change_entry_norevision_view.html.erb
@@ -0,0 +1,39 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2010-2011 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+<%
+parameters = request.parameters
+path = parameters['path']
+rev = parameters['rev']
+repository_id = @repository.identifier_param if @repository.respond_to?("identifier_param")
+unless path.blank? or path.empty?
+ changesets = @repository.latest_changesets(path, rev, Setting.repository_log_display_limit.to_i)
+ change = changesets[0]
+
+ if change
+ link = link_to(l(:label_add_review), {:controller => 'code_review',
+ :action => 'forward_to_revision', :id => project, :path => path, :rev => rev, :repository_id => repository_id},
+ :class => 'icon icon-edit')
+ %>
+
+
+ <% end %>
+
+<% end %>
\ No newline at end of file
diff --git a/plugins/redmine_code_review/app/views/code_review/_change_repository_view.html.erb b/plugins/redmine_code_review/app/views/code_review/_change_repository_view.html.erb
new file mode 100644
index 00000000..6c7932b4
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_change_repository_view.html.erb
@@ -0,0 +1,41 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2010-2012 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+<%
+
+if @changesets
+ changeset_ids = ''
+ @changesets.each { |changeset|
+ changeset_ids << changeset.revision
+ changeset_ids << ','
+ }
+
+ repository_id = @repository.identifier_param if @repository.respond_to?("identifier_param")
+ url = url_for :controller => 'code_review', :action => 'update_revisions_view', :id => project, :repository_id => repository_id
+%>
+
+
+
+
+
+
+<% end %>
\ No newline at end of file
diff --git a/plugins/redmine_code_review/app/views/code_review/_change_revision_view.html.erb b/plugins/redmine_code_review/app/views/code_review/_change_revision_view.html.erb
new file mode 100644
index 00000000..6f09ea90
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_change_revision_view.html.erb
@@ -0,0 +1,73 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2010-2011 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+<%
+repository_id = @repository.identifier_param if @repository.respond_to?("identifier_param")
+if @changeset
+ urlprefix = url_for(:controller => 'repositories', :action => 'revisions', :id => project, :repository_id => repository_id) +
+ '/' + @changeset.identifier + '/entry'
+%>
+
+
+
+<% end %>
\ No newline at end of file
diff --git a/plugins/redmine_code_review/app/views/code_review/_history.html.erb b/plugins/redmine_code_review/app/views/code_review/_history.html.erb
new file mode 100644
index 00000000..c464a444
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_history.html.erb
@@ -0,0 +1,84 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2009 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+<% for journal in journals %>
+
+
+ <% if not journal.initial? %>
+
+
+ <%
+ header = <<-HTML
+
+ HTML
+
+ if not journal.notes.blank?
+ if User.current.logged?
+ editable = User.current.allowed_to?(:edit_issue_notes, journal.project)
+ if journal.user == User.current
+ editable ||= User.current.allowed_to?(:edit_own_issue_notes, journal.project)
+ end
+ end
+
+ links = [].tap do |l|
+ if editable
+ l << link_to_in_place_notes_editor(image_tag('edit.png'), "journal-#{journal.id}-notes",
+ { :controller => 'journals', :action => 'edit', :id => journal },
+ :title => l(:button_edit))
+ end
+ end
+
+ css_classes = "wiki"
+ css_classes << " editable" if editable
+
+ content = ''
+ content << content_tag('div', links.join(' '), :class => 'contextual') unless links.empty?
+ content << textilizable(journal, :notes)
+
+ header << content_tag("div", content, :id => "journal-#{journal.id}-notes", :class => css_classes)
+ end
+ %>
+
+
+ <%
+ details = ''
+ if journal.details.any?
+ content = journal.details.collect do |detail|
+ if d = journal.render_detail(detail)
+ content_tag("li", d)
+ end
+ end.compact.join(' ')
+
+ details = content_tag("ul", content, :class => "details journal-attributes") unless content.empty?
+ end
+ %>
+
+
+ <%= content_tag "div", "#{header}#{details}",
+ { :id => "change-#{journal.id}", :class => journal.css_classes } %>
+
+ <% end %>
+
+<% end %>
diff --git a/plugins/redmine_code_review/app/views/code_review/_html_header.html.erb b/plugins/redmine_code_review/app/views/code_review/_html_header.html.erb
new file mode 100644
index 00000000..bc277caf
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_html_header.html.erb
@@ -0,0 +1,30 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2010-2012 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+<% if @project and @project.module_enabled?('code_review') %>
+ <%
+ baseurl = Redmine::Utils.relative_url_root
+
+ -%>
+ <%= javascript_include_tag(baseurl + "/plugin_assets/redmine_code_review/javascripts/code_review.js") %>
+ <%= javascript_include_tag(baseurl + '/javascripts/jstoolbar/jstoolbar.js') %>
+ <%= javascript_include_tag(baseurl + '/javascripts/jstoolbar/textile.js') %>
+ <%= javascript_include_tag(baseurl + "/javascripts/jstoolbar/lang/jstoolbar-#{@project.current_language}.js") %>
+ <%= stylesheet_link_tag(baseurl + "/plugin_assets/redmine_code_review/stylesheets/code_review.css") %>
+ <%= stylesheet_link_tag(baseurl + "/stylesheets/jstoolbar.css") %>
+<% end %>
\ No newline at end of file
diff --git a/plugins/redmine_code_review/app/views/code_review/_issues_show_details_bottom.html.erb b/plugins/redmine_code_review/app/views/code_review/_issues_show_details_bottom.html.erb
new file mode 100644
index 00000000..e60198ff
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_issues_show_details_bottom.html.erb
@@ -0,0 +1,56 @@
+<%#
+# To change this template, choose Tools | Templates
+# and open the template in the editor.
+%>
+
+<%
+unless User.current.allowed_to?({:controller => 'code_review', :action => 'show'}, project)
+ return
+end
+
+%>
+
+<% if issue.code_review %>
+<%
+review = issue.code_review
+%>
+
+
+<% end %>
+
diff --git a/plugins/redmine_code_review/app/views/code_review/_new_form.html.erb b/plugins/redmine_code_review/app/views/code_review/_new_form.html.erb
new file mode 100644
index 00000000..81feda16
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_new_form.html.erb
@@ -0,0 +1,121 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2013 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+
+
+
+
+
diff --git a/plugins/redmine_code_review/app/views/code_review/_reply.html.erb b/plugins/redmine_code_review/app/views/code_review/_reply.html.erb
new file mode 100644
index 00000000..7fccf0aa
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_reply.html.erb
@@ -0,0 +1,36 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2009 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+
+
+
+
\ No newline at end of file
diff --git a/plugins/redmine_code_review/app/views/code_review/_show.html.erb b/plugins/redmine_code_review/app/views/code_review/_show.html.erb
new file mode 100644
index 00000000..560447b9
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_show.html.erb
@@ -0,0 +1,187 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2012 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+
+
+
\ No newline at end of file
diff --git a/plugins/redmine_code_review/app/views/code_review/_update_diff_view.html.erb b/plugins/redmine_code_review/app/views/code_review/_update_diff_view.html.erb
new file mode 100644
index 00000000..0d38e3ae
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_update_diff_view.html.erb
@@ -0,0 +1,77 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2012 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+
+
+
+
diff --git a/plugins/redmine_code_review/app/views/code_review/_update_revisions.html.erb b/plugins/redmine_code_review/app/views/code_review/_update_revisions.html.erb
new file mode 100644
index 00000000..48b9289e
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/_update_revisions.html.erb
@@ -0,0 +1,49 @@
+<%#
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2011 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+%>
+
+
+
+
diff --git a/plugins/redmine_code_review/app/views/code_review/index.html.erb b/plugins/redmine_code_review/app/views/code_review/index.html.erb
new file mode 100644
index 00000000..c82a9c0b
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review/index.html.erb
@@ -0,0 +1,101 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2012 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+
+
+
+
+ <% end %>
+
+ <% content_for :header_tags do %>
+ <%= stylesheet_link_tag "code_review.css", :plugin => "redmine_code_review", :media => "screen" %>
+ <% end %>
+
diff --git a/plugins/redmine_code_review/app/views/code_review_settings/_filters.html.erb b/plugins/redmine_code_review/app/views/code_review_settings/_filters.html.erb
new file mode 100644
index 00000000..ec06aa1f
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review_settings/_filters.html.erb
@@ -0,0 +1,117 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2012 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+
+
diff --git a/plugins/redmine_code_review/app/views/code_review_settings/_show.html.erb b/plugins/redmine_code_review/app/views/code_review_settings/_show.html.erb
new file mode 100644
index 00000000..74454d49
--- /dev/null
+++ b/plugins/redmine_code_review/app/views/code_review_settings/_show.html.erb
@@ -0,0 +1,163 @@
+<%
+# Code Review plugin for Redmine
+# Copyright (C) 2010-2012 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-%>
+
+ <%= submit_tag l(:button_update) %>
+ <% end %>
+
+<%= wikitoolbar_for 'auto_assign_description' %>
diff --git a/plugins/redmine_code_review/assets/images/closed_review.png b/plugins/redmine_code_review/assets/images/closed_review.png
new file mode 100644
index 00000000..13659325
Binary files /dev/null and b/plugins/redmine_code_review/assets/images/closed_review.png differ
diff --git a/plugins/redmine_code_review/assets/images/review.png b/plugins/redmine_code_review/assets/images/review.png
new file mode 100644
index 00000000..5ff08181
Binary files /dev/null and b/plugins/redmine_code_review/assets/images/review.png differ
diff --git a/plugins/redmine_code_review/assets/javascripts/code_review.js b/plugins/redmine_code_review/assets/javascripts/code_review.js
new file mode 100644
index 00000000..625f376c
--- /dev/null
+++ b/plugins/redmine_code_review/assets/javascripts/code_review.js
@@ -0,0 +1,354 @@
+/*
+# Code Review plugin for Redmine
+# Copyright (C) 2009-2013 Haruyuki Iida
+#
+# 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 2
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+var topZindex = 1000;
+var action_type = '';
+var rev = '';
+var rev_to = '';
+var path = '';
+var urlprefix = '';
+var review_form_dialog = null;
+var add_form_title = null;
+var review_dialog_title = null;
+var repository_id = null;
+var filenames = [];
+
+var ReviewCount = function(total, open, progress){
+ this.total = total;
+ this.open = open;
+ this.closed = total - open;
+ this.progress = progress
+};
+
+var CodeReview = function(id) {
+ this.id = id;
+ this.path = '';
+ this.line = 0;
+ this.url = '';
+ this.is_closed = false;
+};
+
+var review_counts = new Array();
+var code_reviews_map = new Array();
+var code_reviews_dialog_map = new Array();
+
+function UpdateRepositoryView(title) {
+ var header = $("table.changesets thead tr:first");
+ var th = $('