Allow issue grouping by custom field (#2679).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3071 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
2a3a6da45a
commit
71bc44a89d
@ -64,7 +64,7 @@ class IssuesController < ApplicationController
|
|||||||
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
|
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
|
||||||
@issue_pages = Paginator.new self, @issue_count, limit, params['page']
|
@issue_pages = Paginator.new self, @issue_count, limit, params['page']
|
||||||
@issues = Issue.find :all, :order => [@query.group_by_sort_order, sort_clause].compact.join(','),
|
@issues = Issue.find :all, :order => [@query.group_by_sort_order, sort_clause].compact.join(','),
|
||||||
:include => [ :assigned_to, :status, :tracker, :project, :priority, :category, :fixed_version ],
|
:include => [ :assigned_to, :status, :tracker, :project, :priority, :category, :fixed_version ],
|
||||||
:conditions => @query.statement,
|
:conditions => @query.statement,
|
||||||
:limit => limit,
|
:limit => limit,
|
||||||
:offset => @issue_pages.current.offset
|
:offset => @issue_pages.current.offset
|
||||||
@ -73,7 +73,7 @@ class IssuesController < ApplicationController
|
|||||||
if @query.grouped?
|
if @query.grouped?
|
||||||
# Retrieve the issue count by group
|
# Retrieve the issue count by group
|
||||||
@issue_count_by_group = begin
|
@issue_count_by_group = begin
|
||||||
Issue.count(:group => @query.group_by, :include => [:status, :project], :conditions => @query.statement)
|
Issue.count(:group => @query.group_by_statement, :include => [:status, :project], :conditions => @query.statement)
|
||||||
# Rails will raise an (unexpected) error if there's only a nil group value
|
# Rails will raise an (unexpected) error if there's only a nil group value
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
{nil => @issue_count}
|
{nil => @issue_count}
|
||||||
|
@ -27,6 +27,15 @@ module QueriesHelper
|
|||||||
content_tag('th', column.caption)
|
content_tag('th', column.caption)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def column_value(column, issue)
|
||||||
|
if column.is_a?(QueryCustomFieldColumn)
|
||||||
|
cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
|
||||||
|
show_value(cv)
|
||||||
|
else
|
||||||
|
value = issue.send(column.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def column_content(column, issue)
|
def column_content(column, issue)
|
||||||
if column.is_a?(QueryCustomFieldColumn)
|
if column.is_a?(QueryCustomFieldColumn)
|
||||||
cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
|
cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
|
||||||
|
@ -23,6 +23,9 @@ class QueryColumn
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.sortable = options[:sortable]
|
self.sortable = options[:sortable]
|
||||||
self.groupable = options[:groupable] || false
|
self.groupable = options[:groupable] || false
|
||||||
|
if groupable == true
|
||||||
|
self.groupable = name.to_s
|
||||||
|
end
|
||||||
self.default_order = options[:default_order]
|
self.default_order = options[:default_order]
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -41,6 +44,10 @@ class QueryCustomFieldColumn < QueryColumn
|
|||||||
def initialize(custom_field)
|
def initialize(custom_field)
|
||||||
self.name = "cf_#{custom_field.id}".to_sym
|
self.name = "cf_#{custom_field.id}".to_sym
|
||||||
self.sortable = custom_field.order_statement || false
|
self.sortable = custom_field.order_statement || false
|
||||||
|
if %w(list date bool int).include?(custom_field.field_format)
|
||||||
|
self.groupable = custom_field.order_statement
|
||||||
|
end
|
||||||
|
self.groupable ||= false
|
||||||
@cf = custom_field
|
@cf = custom_field
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -312,6 +319,10 @@ class Query < ActiveRecord::Base
|
|||||||
groupable_columns.detect {|c| c.name.to_s == group_by}
|
groupable_columns.detect {|c| c.name.to_s == group_by}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def group_by_statement
|
||||||
|
group_by_column.groupable
|
||||||
|
end
|
||||||
|
|
||||||
def project_statement
|
def project_statement
|
||||||
project_clauses = []
|
project_clauses = []
|
||||||
if project && !@project.descendants.active.empty?
|
if project && !@project.descendants.active.empty?
|
||||||
|
@ -10,11 +10,10 @@
|
|||||||
<%= column_header(column) %>
|
<%= column_header(column) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</tr></thead>
|
</tr></thead>
|
||||||
<% group = false %>
|
<% previous_group = false %>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% issues.each do |issue| -%>
|
<% issues.each do |issue| -%>
|
||||||
<% if @query.grouped? && issue.send(@query.group_by) != group %>
|
<% if @query.grouped? && (group = column_value(@query.group_by_column, issue) || '') != previous_group %>
|
||||||
<% group = issue.send(@query.group_by) %>
|
|
||||||
<% reset_cycle %>
|
<% reset_cycle %>
|
||||||
<tr class="group open">
|
<tr class="group open">
|
||||||
<td colspan="<%= query.columns.size + 2 %>">
|
<td colspan="<%= query.columns.size + 2 %>">
|
||||||
@ -22,6 +21,7 @@
|
|||||||
<%= group.blank? ? 'None' : group %> <span class="count">(<%= @issue_count_by_group[group] %>)</span>
|
<%= group.blank? ? 'None' : group %> <span class="count">(<%= @issue_count_by_group[group] %>)</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<% previous_group = group %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %>">
|
<tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %>">
|
||||||
<td class="checkbox"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
|
<td class="checkbox"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
|
||||||
|
19
test/fixtures/queries.yml
vendored
19
test/fixtures/queries.yml
vendored
@ -134,4 +134,23 @@ queries_008:
|
|||||||
|
|
||||||
user_id: 2
|
user_id: 2
|
||||||
column_names:
|
column_names:
|
||||||
|
queries_009:
|
||||||
|
id: 9
|
||||||
|
project_id:
|
||||||
|
is_public: true
|
||||||
|
name: Open issues grouped by list custom field
|
||||||
|
filters: |
|
||||||
|
---
|
||||||
|
status_id:
|
||||||
|
:values:
|
||||||
|
- "1"
|
||||||
|
:operator: o
|
||||||
|
|
||||||
|
user_id: 1
|
||||||
|
column_names:
|
||||||
|
group_by: cf_1
|
||||||
|
sort_criteria: |
|
||||||
|
---
|
||||||
|
- - priority
|
||||||
|
- desc
|
||||||
|
|
||||||
|
@ -171,12 +171,26 @@ class IssuesControllerTest < ActionController::TestCase
|
|||||||
assert_nil assigns(:issue_count_by_group)
|
assert_nil assigns(:issue_count_by_group)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_index_with_grouped_query
|
def test_index_with_query_grouped_by_tracker
|
||||||
get :index, :project_id => 1, :query_id => 6
|
get :index, :project_id => 1, :query_id => 6
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template 'index.rhtml'
|
assert_template 'index.rhtml'
|
||||||
assert_not_nil assigns(:issues)
|
assert_not_nil assigns(:issues)
|
||||||
assert_not_nil assigns(:issue_count_by_group)
|
count_by_group = assigns(:issue_count_by_group)
|
||||||
|
assert_kind_of Hash, count_by_group
|
||||||
|
assert_kind_of Tracker, count_by_group.keys.first
|
||||||
|
assert_not_nil count_by_group[Tracker.find(1)]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_index_with_query_grouped_by_list_custom_field
|
||||||
|
get :index, :project_id => 1, :query_id => 9
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'index.rhtml'
|
||||||
|
assert_not_nil assigns(:issues)
|
||||||
|
count_by_group = assigns(:issue_count_by_group)
|
||||||
|
assert_kind_of Hash, count_by_group
|
||||||
|
assert_kind_of String, count_by_group.keys.first
|
||||||
|
assert_not_nil count_by_group['MySQL']
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_index_csv_with_project
|
def test_index_csv_with_project
|
||||||
|
@ -197,6 +197,11 @@ class QueryTest < ActiveSupport::TestCase
|
|||||||
assert q.has_column?(c)
|
assert q.has_column?(c)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_groupable_columns_should_include_custom_fields
|
||||||
|
q = Query.new
|
||||||
|
assert q.groupable_columns.detect {|c| c.is_a? QueryCustomFieldColumn}
|
||||||
|
end
|
||||||
|
|
||||||
def test_default_sort
|
def test_default_sort
|
||||||
q = Query.new
|
q = Query.new
|
||||||
assert_equal [], q.sort_criteria
|
assert_equal [], q.sort_criteria
|
||||||
|
Loading…
x
Reference in New Issue
Block a user