code=Code
color=Color
compare=Compare
+component=Component
configurable=Configurable
configure=Configure
confirm=Confirm
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
+
#------------------------------------------------------------------------------
#
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
\ No newline at end of file
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.
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
--- /dev/null
+#
+# 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
\ No newline at end of file
<%
- 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>
<%
--- /dev/null
+<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>
\ No newline at end of file
+++ /dev/null
-<div id="reviews-search">
- <div id="content">
- <%= render :partial => "list" -%>
- </div>
-</div>
\ No newline at end of file
--- /dev/null
+<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>
\ No newline at end of file