action_plans.date_not_valid=Date not valid
action_plans.date_cant_be_in_past=The dead-line can't be in the past
action_plans.x_out_of_x_reviews_solved={0} of {1} reviews solved
+action_plans.resolved_reviews_x_percent=Resolved reviews - {0}% ({1} reviews)
+action_plans.open_reviews_x_percent=Open reviews - {0}% ({1} reviews)
#------------------------------------------------------------------------------
--- /dev/null
+#
+# Sonar, entreprise quality control tool.
+# Copyright (C) 2008-2011 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# Sonar is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# Sonar 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Sonar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+#
+
+class ProjectReviewsController < ApplicationController
+
+ SECTION=Navigation::SECTION_RESOURCE
+
+ def index
+ @project=Project.by_key(params[:projects])
+ not_found("Project not found") unless @project
+ access_denied unless is_admin?(@project)
+
+ found_reviews = Review.search(params)
+ @reviews = select_authorized(:user, found_reviews, :project)
+ if found_reviews.size != @reviews.size
+ @security_exclusions = true
+ end
+
+ # table pagination
+ @page_size = 20
+ @page_size = params[:page_size].to_i if Api::Utils.is_number?(params[:page_size]) && params[:page_size].to_i > 5
+ @total_number = @reviews.size
+ if @reviews.size > @page_size
+ @page_id = (params[:page_id] ? params[:page_id].to_i : 1)
+ @page_count = @reviews.size / @page_size
+ @page_count += 1 if (@reviews.size % @page_size > 0)
+ from = (@page_id-1) * @page_size
+ to = (@page_id*@page_size)-1
+ to = @reviews.size-1 if to >= @reviews.size
+ @reviews = @reviews[from..to]
+ end
+ end
+
+end
def progress
total_reviews = reviews.size
open_reviews = reviews.select{|r| r.open? || r.reopened?}.size
- {:total => total_reviews, :open => open_reviews}
+ {:total => total_reviews, :open => open_reviews, :resolved => total_reviews-open_reviews}
end
private
conditions=[]
values={}
-
if options['id'].present?
conditions << 'id=:id'
values[:id]=options['id'].to_i
conditions << 'id in (:ids)'
values[:ids]=ids.map { |id| id.to_i }
else
-
-
+
# --- 'review_type' is deprecated since 2.9 ---
# Following code just for backward compatibility
review_type = options['review_type']
values[:assignees]=assignees.map { |user_id| user_id.to_i }
end
end
+
+ action_plan_id = options['action_plan_id']
+ if action_plan_id
+ action_plan = ActionPlan.find action_plan_id.to_i, :include => 'reviews'
+ if action_plan
+ conditions << 'id in (:ids)'
+ values[:ids]=action_plan.reviews.map { |r| r.id }
+ end
+ end
from=options['from']
if from
<%
- open_reviews_url = link_to action_plan.progress[:open].to_s,
- :controller => 'reviews', :action => 'index',
- :action_plans => [action_plan.id], :statuses => [Review::STATUS_OPEN, Review::STATUS_REOPENED], :assignee_login => ''
+ unless action_plan.progress[:total]==0
+ options = {:controller => 'project_reviews', :action => 'index', :action_plan_id => action_plan.id, :projects => action_plan.project_id}
- total_reviews_url = link_to action_plan.progress[:total].to_s,
- :controller => 'reviews', :action => 'index',
- :action_plans => [action_plan.id], :statuses => [''], :assignee_login => ''
+ resolved_reviews_link = link_to action_plan.progress[:resolved].to_s, options.merge({:statuses => "#{Review::STATUS_RESOLVED},#{Review::STATUS_CLOSED}"})
+ total_reviews_link = link_to action_plan.progress[:total].to_s, options
+
+ resolved_reviews_url = url_for options.merge({:statuses => "#{Review::STATUS_RESOLVED},#{Review::STATUS_CLOSED}"})
+ open_reviews_url = url_for options.merge({:statuses => "#{Review::STATUS_OPEN},#{Review::STATUS_REOPENED}"})
+
+ percent_resolved = (action_plan.progress[:resolved]*100/action_plan.progress[:total]).to_i
+ percent_open = (action_plan.progress[:open]*100/action_plan.progress[:total]).to_i
+
+ tooltip_resolved = message('action_plans.resolved_reviews_x_percent', :params => [percent_resolved.to_s, action_plan.progress[:resolved].to_s])
+ tooltip_open = message('action_plans.open_reviews_x_percent', :params => [percent_open.to_s, action_plan.progress[:open].to_s])
%>
+
<div class="progress">
- <div class="bar">
- <div style="width:<%= action_plan.progress[:total]==0 ? '0' : action_plan.progress[:open]*100/action_plan.progress[:total] -%>%;"> </div>
- </div>
- <div class="note"><%= message('action_plans.x_out_of_x_reviews_solved', :params => [open_reviews_url, total_reviews_url]) -%></div>
-</div>
\ No newline at end of file
+ <table>
+ <tbody>
+ <tr>
+ <td class="resolved" style="width:<%= percent_resolved -%>%;">
+ <a href="<%= resolved_reviews_url -%>" title="<%= tooltip_resolved -%>" alt="<%= tooltip_resolved -%>"></a>
+ </td>
+ <td class="open" style="width:<%= percent_open -%>%;">
+ <a href="<%= open_reviews_url -%>" title="<%= tooltip_open -%>" alt="<%= tooltip_open -%>"></a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="note"><%= message('action_plans.x_out_of_x_reviews_solved', :params => [resolved_reviews_link, total_reviews_link]) -%></div>
+</div>
+
+<% end %>
\ No newline at end of file
vertical-align: top;
}
#actionPlans td.progress {
+ width: 300px;
padding: 0px 40px;
}
</style>
<tr>
<td class="thin nowrap center"><img src="<%= ApplicationController.root_context -%>/images/status/<%= plan.status -%>.png" title="<%= message(plan.status.downcase).capitalize -%>"/></td>
<td class="thin nowrap"><%= h(plan.name) -%></td>
- <td class="thin nowrap" align="right"><%= plan.dead_line ? plan.dead_line.strftime('%Y/%m/%d') : ' ' -%></td>
+ <td class="thin nowrap" align="right" x="<%= plan.dead_line ? plan.dead_line.tv_sec : '' -%>"><%= plan.dead_line ? l(plan.dead_line) : ' ' -%></td>
<td class="progress thin">
<%= render :partial => 'progress', :locals => {:action_plan => plan} -%>
</td>
--- /dev/null
+<div id="reviews-search">
+ <h1><%= message('reviews') -%></h1>
+
+ <%= render :partial => "reviews/list" -%>
+
+</div>
\ No newline at end of file
--- /dev/null
+ <%
+ if @reviews && !@reviews.empty?
+ %>
+ <% if @false_positives=='only' %>
+ <span class="falsePositive"><%= message('reviews.showing_false_positives_only') -%></span>
+ <% end %>
+ <%
+ if params[:from] && params[:to]
+ from = Time.parse(params[:from])
+ to = Time.parse(params[:to])
+ %>
+ <div style="color:#777777; font-size:93%; padding: 4px 0px 4px 10px;">
+ <span style="background-color: #FFF6BF; padding-left: 5px; padding-right: 5px;">
+ <%= message('reviews.reviews_filtered_by_date_x_to_y', :params => [l(from, :format => '%d %B %Y'), l(to, :format => '%d %B %Y')]) -%>
+ </span>
+ </div>
+ <% end %>
+
+ <table id="reviews-list" class="data width100">
+ <thead>
+ <tr>
+ <th width="1%" nowrap>
+ <a href="#" onClick="launchSearch('status', this)"><%= message('status_abbreviated') -%></a>
+ <%= image_tag(@asc ? "asc12.png" : "desc12.png") if @sort == 'status' -%>
+ </th>
+ <th width="1%" nowrap>
+ <a href="#" onClick="launchSearch('id', this)"><%= message('identifier_abbreviated') -%></a>
+ <%= image_tag(@asc ? "asc12.png" : "desc12.png") if @sort == 'id' -%>
+ </th>
+ <th width="1%" nowrap>
+ <a href="#" onClick="launchSearch('severity', this)"><%= message('severity_abbreviated') -%></a>
+ <%= image_tag(@asc ? "asc12.png" : "desc12.png") if @sort == 'severity' -%>
+ </th>
+ <th>
+ <a href="#" onClick="launchSearch('title', this)"><%= message('title') -%></a>
+ <%= image_tag(@asc ? "asc12.png" : "desc12.png") if @sort == 'title' -%>
+ </th>
+ <th width="1%"><%= message('project') -%></th>
+ <th><%= message('assignee') -%></th>
+ <th>
+ <a href="#" onClick="launchSearch('updated_at', this)"><%= message('age') -%></a>
+ <%= image_tag(@asc ? "asc12.png" : "desc12.png") if @sort == 'updated_at' -%>
+ </th>
+ </tr>
+ </thead>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <%= @total_number -%> <%= message('results').downcase -%>
+ <% if @page_count %>
+ |
+ <%= link_to_if @page_id>1, message('paging_previous'), {:overwrite_params => {:page_id => @page_id-1}} %>
+ <% for index in 1..@page_count %>
+ <%= link_to_unless index==@page_id, index.to_s, {:overwrite_params => {:page_id => index}} %>
+ <% end %>
+ <%= link_to_if @page_id<@page_count, message('paging_next'), {:overwrite_params => {:page_id => 1+@page_id}} %>
+ <% end %>
+ </td>
+ </tr>
+ </tfoot>
+ <tbody>
+ <%
+ @reviews.each do |review|
+ comment = review.comments.last
+ %>
+ <tr class="<%= cycle('even', 'odd') -%>">
+ <td><img src="<%= ApplicationController.root_context -%>/images/status/<%= review.status -%>.png" title="<%= message(review.status.downcase).capitalize -%>"/></td>
+ <td>
+ <%= link_to h(review.id), :controller => "reviews", :action => "view", :id => review.id -%>
+ </td>
+ <td><img src="<%= ApplicationController.root_context -%>/images/priority/<%= review.severity -%>.png" title="<%= message(review.severity.downcase).capitalize -%>"/></td>
+ <td>
+ <%= link_to h(review.title), :controller => "reviews", :action => "view", :id => review.id -%>
+ <% if comment %>
+ <div class="comment-excerpt">
+ <img src="<%= ApplicationController.root_context -%>/images/reviews/comment.png"/>
+ <b><%= comment.user.name -%> :</b>
+ <%= comment.excerpt -%>
+ <% end %>
+ </div>
+ </td>
+ <td>
+ <span class="nowrap"><%= review.project.name -%></span>
+ <br/>
+ <span class="note"><%= review.resource.name -%></span></td>
+ <td><%= review.assignee ? h(review.assignee.name) : '-' -%></td>
+ <td><%= distance_of_time_in_words_to_now(review.updated_at) -%></td>
+ </tr>
+ <%
+ end
+ %>
+ </tbody>
+ </table>
+ <%
+ elsif @reviews
+ %>
+ <p><%= message('no_results') -%></p>
+ <%
+ end
+ %>
+
+ <% if @security_exclusions %>
+ <br/>
+
+ <p class="notes"><%= message('results_not_display_due_to_security') -%></p>
+ <% end %>
\ No newline at end of file
-<script>
- function reviewIdFieldModified(field) {
- if (field.value != '') {
- $('statuses').value = ''
- $('severities').value = ''
- $('projects').value = ''
- $('author_login').value = ''
- $('autocompleteText-author_login').value = ''
- $('assignee_login').value = ''
- $('autocompleteText-assignee_login').value = ''
- $('false_positives').value = 'with'
- }
- }
- function launchSearch(columnName, link) {
- $('sort').value = columnName
- if ($('asc').value == "true") {
- $('asc').value = "false";
- } else {
- $('asc').value = "true";
- }
- document.forms[0].submit()
- }
-</script>
<div id="reviews-search">
<h1><%= message('reviews') -%></h1>
<% form_tag({:action => 'index'}, {:method => 'get'}) do %>
<% end %>
- <%
- if @reviews && !@reviews.empty?
- %>
- <% if @false_positives=='only' %>
- <span class="falsePositive"><%= message('reviews.showing_false_positives_only') -%></span>
- <% end %>
- <%
- if params[:from] && params[:to]
- from = Time.parse(params[:from])
- to = Time.parse(params[:to])
- %>
- <div style="color:#777777; font-size:93%; padding: 4px 0px 4px 10px;">
- <span style="background-color: #FFF6BF; padding-left: 5px; padding-right: 5px;">
- <%= message('reviews.reviews_filtered_by_date_x_to_y', :params => [l(from, :format => '%d %B %Y'), l(to, :format => '%d %B %Y')]) -%>
- </span>
- </div>
- <% end %>
-
- <table id="reviews-list" class="data width100">
- <thead>
- <tr>
- <th width="1%" nowrap>
- <a href="#" onClick="launchSearch('status', this)"><%= message('status_abbreviated') -%></a>
- <%= image_tag(@asc ? "asc12.png" : "desc12.png") if @sort == 'status' -%>
- </th>
- <th width="1%" nowrap>
- <a href="#" onClick="launchSearch('id', this)"><%= message('identifier_abbreviated') -%></a>
- <%= image_tag(@asc ? "asc12.png" : "desc12.png") if @sort == 'id' -%>
- </th>
- <th width="1%" nowrap>
- <a href="#" onClick="launchSearch('severity', this)"><%= message('severity_abbreviated') -%></a>
- <%= image_tag(@asc ? "asc12.png" : "desc12.png") if @sort == 'severity' -%>
- </th>
- <th>
- <a href="#" onClick="launchSearch('title', this)"><%= message('title') -%></a>
- <%= image_tag(@asc ? "asc12.png" : "desc12.png") if @sort == 'title' -%>
- </th>
- <th width="1%"><%= message('project') -%></th>
- <th><%= message('assignee') -%></th>
- <th>
- <a href="#" onClick="launchSearch('updated_at', this)"><%= message('age') -%></a>
- <%= image_tag(@asc ? "asc12.png" : "desc12.png") if @sort == 'updated_at' -%>
- </th>
- </tr>
- </thead>
- <tfoot>
- <tr>
- <td colspan="6">
- <%= @total_number -%> <%= message('results').downcase -%>
- <% if @page_count %>
- |
- <%= link_to_if @page_id>1, message('paging_previous'), {:overwrite_params => {:page_id => @page_id-1}} %>
- <% for index in 1..@page_count %>
- <%= link_to_unless index==@page_id, index.to_s, {:overwrite_params => {:page_id => index}} %>
- <% end %>
- <%= link_to_if @page_id<@page_count, message('paging_next'), {:overwrite_params => {:page_id => 1+@page_id}} %>
- <% end %>
- </td>
- </tr>
- </tfoot>
- <tbody>
- <%
- @reviews.each do |review|
- comment = review.comments.last
- %>
- <tr class="<%= cycle('even', 'odd') -%>">
- <td><img src="<%= ApplicationController.root_context -%>/images/status/<%= review.status -%>.png" title="<%= message(review.status.downcase).capitalize -%>"/></td>
- <td>
- <%= link_to h(review.id), :controller => "reviews", :action => "view", :id => review.id -%>
- </td>
- <td><img src="<%= ApplicationController.root_context -%>/images/priority/<%= review.severity -%>.png" title="<%= message(review.severity.downcase).capitalize -%>"/></td>
- <td>
- <%= link_to h(review.title), :controller => "reviews", :action => "view", :id => review.id -%>
- <% if comment %>
- <div class="comment-excerpt">
- <img src="<%= ApplicationController.root_context -%>/images/reviews/comment.png"/>
- <b><%= comment.user.name -%> :</b>
- <%= comment.excerpt -%>
- <% end %>
- </div>
- </td>
- <td>
- <span class="nowrap"><%= review.project.name -%></span>
- <br/>
- <span class="note"><%= review.resource.name -%></span></td>
- <td><%= review.assignee ? h(review.assignee.name) : '-' -%></td>
- <td><%= distance_of_time_in_words_to_now(review.updated_at) -%></td>
- </tr>
- <%
- end
- %>
- </tbody>
- </table>
- <%
- elsif @reviews
- %>
- <p><%= message('no_results') -%></p>
- <%
- end
- %>
-
- <% if @security_exclusions %>
- <br/>
-
- <p class="notes"><%= message('results_not_display_due_to_security') -%></p>
- <% end %>
+ <%= render :partial => "list" -%>
</div>
<script>
+ function reviewIdFieldModified(field) {
+ if (field.value != '') {
+ $('statuses').value = ''
+ $('severities').value = ''
+ $('projects').value = ''
+ $('author_login').value = ''
+ $('autocompleteText-author_login').value = ''
+ $('assignee_login').value = ''
+ $('autocompleteText-assignee_login').value = ''
+ $('false_positives').value = 'with'
+ }
+ }
+ function launchSearch(columnName, link) {
+ $('sort').value = columnName
+ if ($('asc').value == "true") {
+ $('asc').value = "false";
+ } else {
+ $('asc').value = "true";
+ }
+ document.forms[0].submit()
+ }
+
$('review_id').focus();
</script>
\ No newline at end of file
/* ACTION PLANS */
div.progress {
- width: 400px;
+ width: 100%;
margin: 4px;
}
-div.progress div.bar {
+div.progress table {
width: 100%;
- background-color: #CC0000;
- border: none;
- margin-bottom: 4px;
}
-div.progress > div > div {
+div.progress td {
height: 10px;
+}
+
+div.progress td a {
+ display: block; width: 100%; height: 100%;
+}
+
+div.progress td.resolved {
background-color: #078C00;
}
+div.progress td.open {
+ background-color: #CC0000;
+}
+
div.progress div.note {
color: #777777;
font-size: 93%;