Преглед на файлове

SONAR-4301 Add severities filter on issues search page

tags/3.6
Julien Lancelot преди 11 години
родител
ревизия
1bcdcf66d3

+ 18
- 0
plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties Целия файл

@@ -34,6 +34,7 @@ closed=Closed
code=Code
color=Color
compare=Compare
component=Component
configurable=Configurable
configure=Configure
confirm=Confirm
@@ -554,6 +555,23 @@ issue.resolution.FALSE-POSITIVE=False-positive
issue.resolution.FIXED=Fixed
issue.planned_for_x=Planned for {0}

#------------------------------------------------------------------------------
#
# ISSUE FILTERS
#
#------------------------------------------------------------------------------
issue_filter.new_search=New search
issue_filter.header.action_plan=Action plan
issue_filter.header.assignee=Assignee
issue_filter.header.creation_date=Creation date
issue_filter.header.update_date=Update date
issue_filter.criteria.severities=Severities
issue_filter.criteria.project=Project
issue_filter.criteria.status=Status
issue_filter.criteria.assignee=Assignee
issue_filter.criteria.reporter=Reporter
issue_filter.criteria.creation_date=Creation date


#------------------------------------------------------------------------------
#

+ 9
- 7
sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb Целия файл

@@ -21,19 +21,21 @@
class IssuesController < ApplicationController

def index
init_params
@issue_results = Api.issues.find(params)
@paging = @issue_results.paging
@issues = @issue_results.issues
@filter = IssueFilter.new
render :action => 'search'
end

def search
@filter = IssueFilter.new
@filter.criteria=criteria_params
@filter.execute
end


private

def init_params
def criteria_params
params.merge({:controller => nil, :action => nil, :search => nil, :widget_id => nil, :edit => nil})
params['pageSize'] = 25
params['pageIndex'] ||= 1
end

end

+ 66
- 33
sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb Целия файл

@@ -534,39 +534,6 @@ module ApplicationHelper
html
end

#
# Creates a pagination section for the given array (items_array) if its size exceeds the pagination size (default: 20).
# Upon completion of this method, the HTML is returned and the given array contains only the selected elements.
#
# In any case, the HTML that is returned contains the message 'x results', where x is the total number of elements
# in the items_array object.
#
# === Optional parameters
# * page_size: the number of elements to display at the same time (= the pagination size)
#
def paginate_java(pagination)
total = pagination.total.to_i
page_index = pagination.pageIndex() ? pagination.pageIndex().to_i : 1
page_size = pagination.pageSize().to_i || 20
pages = pagination.pages().to_i

html = total.to_s + " " + message('results').downcase

if total > page_size
# render the pagination links
html += " | "
html += link_to_if page_index>1, message('paging_previous'), {:overwrite_params => {:pageIndex => page_index-1}}
html += " "
for index in 1..pages
html += link_to_unless index==page_index, index.to_s, {:overwrite_params => {:pageIndex => index}}
html += " "
end
html += link_to_if page_index<pages, message('paging_next'), {:overwrite_params => {:pageIndex => 1+page_index}}
end

html
end

#
# Used on the reviews listing page (http://localhost:9000/project_reviews)
# Prints a label for the given parameter that is used to filter the review list.
@@ -871,4 +838,70 @@ module ApplicationHelper
html
end


# Add a <tfoot> section to a table with pagination details and links.
# Options :
# :id HTML id of the <tfoot> node
# :colspan number of columns in the table
# :include_loading_icon add a hidden loading icon, only if value is true and if the option :id is set as well. The HTML id of the generated icon
# is '<id>_loading'
def paginate_java(pagination, options={}, &block)
total = pagination.total.to_i
page_index = pagination.pageIndex() ? pagination.pageIndex().to_i : 1
pages = pagination.pages().to_i

html = '<tfoot'
html += " id='#{options[:id]}'" if options[:id]
html += "><tr><td"
html += " colspan='#{options[:colspan]}'" if options[:colspan]
html += '>'
if options[:include_loading_icon] && options[:id]
html += "<img src='#{ApplicationController.root_context}/images/loading-small.gif' style='display: none' id='#{options[:id]}_loading'>"
end
html += '<div'
html += " id='#{options[:id]}_pages'" if options[:id]
html += '>'
html += message('x_results', :params => [total]) if total>0

if pages > 1
max_pages = pages
current_page = page_index
start_page = 1
end_page = max_pages
if max_pages > 20
if current_page < 12
start_page = 1
end_page = 20
elsif current_page > max_pages-10
start_page = max_pages-20
end_page = max_pages
else
start_page = current_page-10
end_page = current_page+9
end
end

html += ' | '
if max_pages > 20 && start_page > 1
html += (current_page!=1 ? yield(message('paging_first'), 1) : message('paging_first'))
html += ' '
end
html += (page_index>1 ? yield(message('paging_previous'), current_page-1) : message('paging_previous'))
html += ' '
for index in start_page..end_page
html += (index != current_page ? yield(index.to_s, index) : index.to_s)
html += ' '
end
html += (page_index<pages ? yield(message('paging_next'), current_page+1) : message('paging_next'))
html += ' '
if max_pages > 20 && end_page < max_pages
html += (current_page != max_pages ? yield(message('paging_last'), max_pages) : message('paging_last'))
html += ' '
end
end
html += '</div></td></tr></tfoot>'
html
end


end

+ 82
- 0
sonar-server/src/main/webapp/WEB-INF/app/models/issue_filter.rb Целия файл

@@ -0,0 +1,82 @@
#
# Sonar, entreprise quality control tool.
# Copyright (C) 2008-2013 SonarSource
# mailto:contact AT sonarsource DOT com
#
# SonarQube 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.
#
# SonarQube 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 this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
require 'set'
class IssueFilter

CRITERIA_SEPARATOR = '|'
CRITERIA_KEY_VALUE_SEPARATOR = ','

attr_reader :paging, :issues, :issues_result

def criteria(key=nil)
@criteria ||= HashWithIndifferentAccess.new
if key
@criteria[key]
else
@criteria
end
end

def criteria=(hash)
@criteria = HashWithIndifferentAccess.new
hash.each_pair do |k, v|
set_criteria_value(k, v)
end
end

def override_criteria(hash)
@criteria ||= HashWithIndifferentAccess.new
hash.each_pair do |k, v|
set_criteria_value(k, v)
end
end

# API used by Displays
def set_criteria_value(key, value)
@criteria ||= HashWithIndifferentAccess.new
if key
if value!=nil && value!='' && value!=['']
value = (value.kind_of?(Array) ? value : value.to_s)
@criteria[key]=value
else
@criteria.delete(key)
end
end
end

def execute
init_results
@issues_result = Api.issues.find(criteria)
@paging = @issues_result.paging
@issues = @issues_result.issues
self
end

private

def init_results
@issues_result = nil
@paging = nil
@issues = nil
criteria['pageSize'] = 25
self
end

end

+ 78
- 62
sonar-server/src/main/webapp/WEB-INF/app/views/issues/_list.html.erb Целия файл

@@ -1,69 +1,85 @@
<%
if @issues && !@issues.empty?
if @filter.issues && !@filter.issues.empty?
colspan = 8
%>
<table id="issues-list" class="data width100">
<thead>
<tr>
<th width="1%" nowrap>
<%= message('status_abbreviated') -%>
</th>
<th width="1%" nowrap>
<%= message('severity_abbreviated') -%>
</th>
<th>
Message
</th>
<th width="1%" nowrap>
Component name
</th>
<th>
<%= message('assignee') -%>
</th>
<th>
Creation date
</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="6">
<%= paginate_java(@paging) -%>
</td>
</tr>
</tfoot>
<tbody>
<%
@issues.each do |issue|
%>
<tr class="<%= cycle('even', 'odd') -%>">
<td>
<img src="<%= ApplicationController.root_context -%>/images/status/<%= issue.status -%>.png" title="<%= message(issue.status.downcase).capitalize -%>"/>
</td>
<td>
<% if issue.severity %>
<div>
<table class="data width100">
<thead>
<tr>
<th width="1%" nowrap>
<%= message('severity_abbreviated') -%>
</th>
<th width="1%" nowrap>
<%= message('status_abbreviated') -%>
</th>
<th>
<%= message('description') -%>
</th>
<th width="1%" nowrap>
<%= message('component') -%>
</th>
<th>
<%= message('issue_filter.header.assignee') -%>
</th>
<th>
<%= message('issue_filter.header.action_plan') -%>
</th>
<th>
<%= message('issue_filter.header.creation_date') -%>
</th>
<th>
<%= message('issue_filter.header.update_date') -%>
</th>
</tr>
</thead>
<tbody>
<%
@filter.issues.each do |issue|
%>
<tr class="<%= cycle('even', 'odd') -%>">
<td>
<img src="<%= ApplicationController.root_context -%>/images/priority/<%= issue.severity -%>.png" title="<%= message(issue.severity.downcase).capitalize -%>"/>
<% end %>
</td>
<td>
<%= link_to h(issue.message), :controller => "issue", :action => "view", :id => issue.key -%>
</td>
<td>
<%= h(@issue_results.component(issue).name) -%>
</td>
<td>
<%= @issue_results.user(issue.assignee).name if issue.assignee -%>
</td>
<td>
<%= human_short_date(Api::Utils.java_to_ruby_datetime(issue.creationDate())) -%>
</td>
</tr>
<%
end
%>
</tbody>
</table>
</td>
<td>
<img src="<%= ApplicationController.root_context -%>/images/status/<%= issue.status -%>.png" title="<%= message(issue.status.downcase).capitalize -%>"/>
</td>
<td>
<%= link_to h(issue.message), :controller => 'issue', :action => 'view', :id => issue.key -%>
</td>
<td>
<%= h @filter.issues_result.component(issue).name -%>
</td>
<td>
<%= h @filter.issues_result.user(issue.assignee).name if issue.assignee -%>
</td>
<td>
<%= h @filter.issues_result.actionPlan(issue).name if issue.actionPlanKey() -%>
</td>
<td>
<%= human_short_date(Api::Utils.java_to_ruby_datetime(issue.creationDate())) -%>
</td>
<td>
<%= human_short_date(Api::Utils.java_to_ruby_datetime(issue.updateDate())) -%>
</td>
</tr>
<%
end
%>
<% if @filter.issues.empty? %>
<tr class="even">
<td colspan="<%= colspan -%>"><%= message 'no_data' -%></td>
</tr>
<% end %>
</tbody>

<%= paginate_java(@filter.paging, :colspan => colspan, :include_loading_icon => true) { |label, page_id|
link_to(label, @filter.criteria.merge({:pageIndex => page_id}))
} -%>

</table>
</div>
<%
elsif @issues
elsif @filter.issues
%>
<p><%= message('no_results') -%></p>
<%

+ 17
- 0
sonar-server/src/main/webapp/WEB-INF/app/views/issues/_sidebar.html.erb Целия файл

@@ -0,0 +1,17 @@
<ul class="sidebar gray-sidebar">
<form method="GET" action="<%= ApplicationController.root_context -%>/issues/search" >
<li class="sidebar-title">
<%= message('issue_filter.new_search') -%>
</li>
<li id="criteria-severity" class="marginbottom5">
<%= message 'issue_filter.criteria.severities' -%>:
<%= dropdown_tag 'severities[]', options_for_select(RulesConfigurationController::RULE_PRIORITIES, @filter.criteria('severities')),
{:width => '100%', :placeholder => message('issue_filter.criteria.severities')},
{:id => 'select-severities', :multiple => true}-%>
</li>
<li>
<input type="submit" name="search" value="<%= message('search_verb') -%>" id="search-button" />
<a href="<%= ApplicationController.root_context -%>/issues" class="link-action"><%= message 'issue_filter.new_search' -%></a>
</li>
</form>
</ul>

+ 0
- 5
sonar-server/src/main/webapp/WEB-INF/app/views/issues/index.html.erb Целия файл

@@ -1,5 +0,0 @@
<div id="reviews-search">
<div id="content">
<%= render :partial => "list" -%>
</div>
</div>

+ 13
- 0
sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb Целия файл

@@ -0,0 +1,13 @@
<div xmlns="http://www.w3.org/1999/html">
<div class="page-split-left">
<%= render :partial => 'issues/sidebar' -%>
</div>

<div class="page-split-right">
<div id="content">
<div class="marginbottom10">
<%= render :partial => 'list' -%>
</div>
</div>
</div>
</div>

Loading…
Отказ
Запис