##// END OF EJS Templates
Allow issue grouping by custom field (#2679)....
Jean-Philippe Lang -
r2957:71bc44a89dce
parent child
Show More
@@ -64,7 +64,7 class IssuesController < ApplicationController
64 @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
64 @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
65 @issue_pages = Paginator.new self, @issue_count, limit, params['page']
65 @issue_pages = Paginator.new self, @issue_count, limit, params['page']
66 @issues = Issue.find :all, :order => [@query.group_by_sort_order, sort_clause].compact.join(','),
66 @issues = Issue.find :all, :order => [@query.group_by_sort_order, sort_clause].compact.join(','),
67 :include => [ :assigned_to, :status, :tracker, :project, :priority, :category, :fixed_version ],
67 :include => [ :assigned_to, :status, :tracker, :project, :priority, :category, :fixed_version ],
68 :conditions => @query.statement,
68 :conditions => @query.statement,
69 :limit => limit,
69 :limit => limit,
70 :offset => @issue_pages.current.offset
70 :offset => @issue_pages.current.offset
@@ -73,7 +73,7 class IssuesController < ApplicationController
73 if @query.grouped?
73 if @query.grouped?
74 # Retrieve the issue count by group
74 # Retrieve the issue count by group
75 @issue_count_by_group = begin
75 @issue_count_by_group = begin
76 Issue.count(:group => @query.group_by, :include => [:status, :project], :conditions => @query.statement)
76 Issue.count(:group => @query.group_by_statement, :include => [:status, :project], :conditions => @query.statement)
77 # Rails will raise an (unexpected) error if there's only a nil group value
77 # Rails will raise an (unexpected) error if there's only a nil group value
78 rescue ActiveRecord::RecordNotFound
78 rescue ActiveRecord::RecordNotFound
79 {nil => @issue_count}
79 {nil => @issue_count}
@@ -27,6 +27,15 module QueriesHelper
27 content_tag('th', column.caption)
27 content_tag('th', column.caption)
28 end
28 end
29
29
30 def column_value(column, issue)
31 if column.is_a?(QueryCustomFieldColumn)
32 cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
33 show_value(cv)
34 else
35 value = issue.send(column.name)
36 end
37 end
38
30 def column_content(column, issue)
39 def column_content(column, issue)
31 if column.is_a?(QueryCustomFieldColumn)
40 if column.is_a?(QueryCustomFieldColumn)
32 cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
41 cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
@@ -23,6 +23,9 class QueryColumn
23 self.name = name
23 self.name = name
24 self.sortable = options[:sortable]
24 self.sortable = options[:sortable]
25 self.groupable = options[:groupable] || false
25 self.groupable = options[:groupable] || false
26 if groupable == true
27 self.groupable = name.to_s
28 end
26 self.default_order = options[:default_order]
29 self.default_order = options[:default_order]
27 end
30 end
28
31
@@ -41,6 +44,10 class QueryCustomFieldColumn < QueryColumn
41 def initialize(custom_field)
44 def initialize(custom_field)
42 self.name = "cf_#{custom_field.id}".to_sym
45 self.name = "cf_#{custom_field.id}".to_sym
43 self.sortable = custom_field.order_statement || false
46 self.sortable = custom_field.order_statement || false
47 if %w(list date bool int).include?(custom_field.field_format)
48 self.groupable = custom_field.order_statement
49 end
50 self.groupable ||= false
44 @cf = custom_field
51 @cf = custom_field
45 end
52 end
46
53
@@ -312,6 +319,10 class Query < ActiveRecord::Base
312 groupable_columns.detect {|c| c.name.to_s == group_by}
319 groupable_columns.detect {|c| c.name.to_s == group_by}
313 end
320 end
314
321
322 def group_by_statement
323 group_by_column.groupable
324 end
325
315 def project_statement
326 def project_statement
316 project_clauses = []
327 project_clauses = []
317 if project && !@project.descendants.active.empty?
328 if project && !@project.descendants.active.empty?
@@ -10,11 +10,10
10 <%= column_header(column) %>
10 <%= column_header(column) %>
11 <% end %>
11 <% end %>
12 </tr></thead>
12 </tr></thead>
13 <% group = false %>
13 <% previous_group = false %>
14 <tbody>
14 <tbody>
15 <% issues.each do |issue| -%>
15 <% issues.each do |issue| -%>
16 <% if @query.grouped? && issue.send(@query.group_by) != group %>
16 <% if @query.grouped? && (group = column_value(@query.group_by_column, issue) || '') != previous_group %>
17 <% group = issue.send(@query.group_by) %>
18 <% reset_cycle %>
17 <% reset_cycle %>
19 <tr class="group open">
18 <tr class="group open">
20 <td colspan="<%= query.columns.size + 2 %>">
19 <td colspan="<%= query.columns.size + 2 %>">
@@ -22,6 +21,7
22 <%= group.blank? ? 'None' : group %> <span class="count">(<%= @issue_count_by_group[group] %>)</span>
21 <%= group.blank? ? 'None' : group %> <span class="count">(<%= @issue_count_by_group[group] %>)</span>
23 </td>
22 </td>
24 </tr>
23 </tr>
24 <% previous_group = group %>
25 <% end %>
25 <% end %>
26 <tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %>">
26 <tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %>">
27 <td class="checkbox"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
27 <td class="checkbox"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
@@ -134,4 +134,23 queries_008:
134
134
135 user_id: 2
135 user_id: 2
136 column_names:
136 column_names:
137 queries_009:
138 id: 9
139 project_id:
140 is_public: true
141 name: Open issues grouped by list custom field
142 filters: |
143 ---
144 status_id:
145 :values:
146 - "1"
147 :operator: o
148
149 user_id: 1
150 column_names:
151 group_by: cf_1
152 sort_criteria: |
153 ---
154 - - priority
155 - desc
137
156
@@ -171,12 +171,26 class IssuesControllerTest < ActionController::TestCase
171 assert_nil assigns(:issue_count_by_group)
171 assert_nil assigns(:issue_count_by_group)
172 end
172 end
173
173
174 def test_index_with_grouped_query
174 def test_index_with_query_grouped_by_tracker
175 get :index, :project_id => 1, :query_id => 6
175 get :index, :project_id => 1, :query_id => 6
176 assert_response :success
176 assert_response :success
177 assert_template 'index.rhtml'
177 assert_template 'index.rhtml'
178 assert_not_nil assigns(:issues)
178 assert_not_nil assigns(:issues)
179 assert_not_nil assigns(:issue_count_by_group)
179 count_by_group = assigns(:issue_count_by_group)
180 assert_kind_of Hash, count_by_group
181 assert_kind_of Tracker, count_by_group.keys.first
182 assert_not_nil count_by_group[Tracker.find(1)]
183 end
184
185 def test_index_with_query_grouped_by_list_custom_field
186 get :index, :project_id => 1, :query_id => 9
187 assert_response :success
188 assert_template 'index.rhtml'
189 assert_not_nil assigns(:issues)
190 count_by_group = assigns(:issue_count_by_group)
191 assert_kind_of Hash, count_by_group
192 assert_kind_of String, count_by_group.keys.first
193 assert_not_nil count_by_group['MySQL']
180 end
194 end
181
195
182 def test_index_csv_with_project
196 def test_index_csv_with_project
@@ -197,6 +197,11 class QueryTest < ActiveSupport::TestCase
197 assert q.has_column?(c)
197 assert q.has_column?(c)
198 end
198 end
199
199
200 def test_groupable_columns_should_include_custom_fields
201 q = Query.new
202 assert q.groupable_columns.detect {|c| c.is_a? QueryCustomFieldColumn}
203 end
204
200 def test_default_sort
205 def test_default_sort
201 q = Query.new
206 q = Query.new
202 assert_equal [], q.sort_criteria
207 assert_equal [], q.sort_criteria
General Comments 0
You need to be logged in to leave comments. Login now