code=Code | code=Code | ||||
color=Color | color=Color | ||||
compare=Compare | compare=Compare | ||||
component=Component | |||||
configurable=Configurable | configurable=Configurable | ||||
configure=Configure | configure=Configure | ||||
confirm=Confirm | confirm=Confirm | ||||
issue.resolution.FIXED=Fixed | issue.resolution.FIXED=Fixed | ||||
issue.planned_for_x=Planned for {0} | 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 | |||||
#------------------------------------------------------------------------------ | #------------------------------------------------------------------------------ | ||||
# | # |
class IssuesController < ApplicationController | class IssuesController < ApplicationController | ||||
def index | 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 | end | ||||
private | private | ||||
def init_params | |||||
def criteria_params | |||||
params.merge({:controller => nil, :action => nil, :search => nil, :widget_id => nil, :edit => nil}) | params.merge({:controller => nil, :action => nil, :search => nil, :widget_id => nil, :edit => nil}) | ||||
params['pageSize'] = 25 | |||||
params['pageIndex'] ||= 1 | |||||
end | end | ||||
end | end |
html | html | ||||
end | 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) | # 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. | # Prints a label for the given parameter that is used to filter the review list. | ||||
html | html | ||||
end | 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 | end |
# | |||||
# 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 |
<% | <% | ||||
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 -%>"/> | <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> | <p><%= message('no_results') -%></p> | ||||
<% | <% |
<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> |
<div id="reviews-search"> | |||||
<div id="content"> | |||||
<%= render :partial => "list" -%> | |||||
</div> | |||||
</div> |
<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> |