@@ -27,44 +27,38 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 |
|
||||
39 | def column_content(column, issue) |
|
30 | def column_content(column, issue) | |
40 | if column.is_a?(QueryCustomFieldColumn) |
|
31 | value = column.value(issue) | |
41 | cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id} |
|
32 | ||
42 | show_value(cv) |
|
33 | case value.class.name | |
43 | else |
|
34 | when 'String' | |
44 | value = issue.send(column.name) |
|
35 | if column.name == :subject | |
45 | if value.is_a?(Date) |
|
36 | link_to(h(value), :controller => 'issues', :action => 'show', :id => issue) | |
46 | format_date(value) |
|
37 | else | |
47 | elsif value.is_a?(Time) |
|
38 | h(value) | |
48 | format_time(value) |
|
39 | end | |
|
40 | when 'Time' | |||
|
41 | format_time(value) | |||
|
42 | when 'Date' | |||
|
43 | format_date(value) | |||
|
44 | when 'Fixnum', 'Float' | |||
|
45 | if column.name == :done_ratio | |||
|
46 | progress_bar(value, :width => '80px') | |||
49 | else |
|
47 | else | |
50 | case column.name |
|
48 | value.to_s | |
51 | when :subject |
|
|||
52 | h((!@project.nil? && @project != issue.project) ? "#{issue.project.name} - " : '') + |
|
|||
53 | link_to(h(value), :controller => 'issues', :action => 'show', :id => issue) |
|
|||
54 | when :project |
|
|||
55 | link_to(h(value), :controller => 'projects', :action => 'show', :id => value) |
|
|||
56 | when :assigned_to |
|
|||
57 | link_to_user value |
|
|||
58 | when :author |
|
|||
59 | link_to_user value |
|
|||
60 | when :done_ratio |
|
|||
61 | progress_bar(value, :width => '80px') |
|
|||
62 | when :fixed_version |
|
|||
63 | link_to(h(value), { :controller => 'versions', :action => 'show', :id => issue.fixed_version_id }) |
|
|||
64 | else |
|
|||
65 | h(value) |
|
|||
66 | end |
|
|||
67 | end |
|
49 | end | |
|
50 | when 'User' | |||
|
51 | link_to_user value | |||
|
52 | when 'Project' | |||
|
53 | link_to(h(value), :controller => 'projects', :action => 'show', :id => value) | |||
|
54 | when 'Version' | |||
|
55 | link_to(h(value), :controller => 'versions', :action => 'show', :id => value) | |||
|
56 | when 'TrueClass' | |||
|
57 | l(:general_text_Yes) | |||
|
58 | when 'FalseClass' | |||
|
59 | l(:general_text_No) | |||
|
60 | else | |||
|
61 | h(value) | |||
68 | end |
|
62 | end | |
69 | end |
|
63 | end | |
70 | end |
|
64 | end |
@@ -67,6 +67,25 class CustomField < ActiveRecord::Base | |||||
67 | end |
|
67 | end | |
68 | end |
|
68 | end | |
69 |
|
69 | |||
|
70 | def cast_value(value) | |||
|
71 | casted = nil | |||
|
72 | unless value.blank? | |||
|
73 | case field_format | |||
|
74 | when 'string', 'text', 'list' | |||
|
75 | casted = value | |||
|
76 | when 'date' | |||
|
77 | casted = begin; value.to_date; rescue; nil end | |||
|
78 | when 'bool' | |||
|
79 | casted = (value == '1' ? true : false) | |||
|
80 | when 'int' | |||
|
81 | casted = value.to_i | |||
|
82 | when 'float' | |||
|
83 | casted = value.to_f | |||
|
84 | end | |||
|
85 | end | |||
|
86 | casted | |||
|
87 | end | |||
|
88 | ||||
70 | # Returns a ORDER BY clause that can used to sort customized |
|
89 | # Returns a ORDER BY clause that can used to sort customized | |
71 | # objects by their value of the custom field. |
|
90 | # objects by their value of the custom field. | |
72 | # Returns false, if the custom field can not be used for sorting. |
|
91 | # Returns false, if the custom field can not be used for sorting. |
@@ -37,6 +37,10 class QueryColumn | |||||
37 | def sortable? |
|
37 | def sortable? | |
38 | !sortable.nil? |
|
38 | !sortable.nil? | |
39 | end |
|
39 | end | |
|
40 | ||||
|
41 | def value(issue) | |||
|
42 | issue.send name | |||
|
43 | end | |||
40 | end |
|
44 | end | |
41 |
|
45 | |||
42 | class QueryCustomFieldColumn < QueryColumn |
|
46 | class QueryCustomFieldColumn < QueryColumn | |
@@ -58,6 +62,11 class QueryCustomFieldColumn < QueryColumn | |||||
58 | def custom_field |
|
62 | def custom_field | |
59 | @cf |
|
63 | @cf | |
60 | end |
|
64 | end | |
|
65 | ||||
|
66 | def value(issue) | |||
|
67 | cv = issue.custom_values.detect {|v| v.custom_field_id == @cf.id} | |||
|
68 | cv && @cf.cast_value(cv.value) | |||
|
69 | end | |||
61 | end |
|
70 | end | |
62 |
|
71 | |||
63 | class Query < ActiveRecord::Base |
|
72 | class Query < ActiveRecord::Base | |
@@ -407,16 +416,20 class Query < ActiveRecord::Base | |||||
407 |
|
416 | |||
408 | # Returns the issue count by group or nil if query is not grouped |
|
417 | # Returns the issue count by group or nil if query is not grouped | |
409 | def issue_count_by_group |
|
418 | def issue_count_by_group | |
|
419 | r = nil | |||
410 | if grouped? |
|
420 | if grouped? | |
411 | begin |
|
421 | begin | |
412 | # Rails will raise an (unexpected) RecordNotFound if there's only a nil group value |
|
422 | # Rails will raise an (unexpected) RecordNotFound if there's only a nil group value | |
413 | Issue.count(:group => group_by_statement, :include => [:status, :project], :conditions => statement) |
|
423 | r = Issue.count(:group => group_by_statement, :include => [:status, :project], :conditions => statement) | |
414 | rescue ActiveRecord::RecordNotFound |
|
424 | rescue ActiveRecord::RecordNotFound | |
415 | {nil => issue_count} |
|
425 | r = {nil => issue_count} | |
|
426 | end | |||
|
427 | c = group_by_column | |||
|
428 | if c.is_a?(QueryCustomFieldColumn) | |||
|
429 | r = r.keys.inject({}) {|h, k| h[c.custom_field.cast_value(k)] = r[k]; h} | |||
416 | end |
|
430 | end | |
417 | else |
|
|||
418 | nil |
|
|||
419 | end |
|
431 | end | |
|
432 | r | |||
420 | rescue ::ActiveRecord::StatementInvalid => e |
|
433 | rescue ::ActiveRecord::StatementInvalid => e | |
421 | raise StatementInvalid.new(e.message) |
|
434 | raise StatementInvalid.new(e.message) | |
422 | end |
|
435 | end |
@@ -13,12 +13,12 | |||||
13 | <% previous_group = false %> |
|
13 | <% previous_group = false %> | |
14 | <tbody> |
|
14 | <tbody> | |
15 | <% issues.each do |issue| -%> |
|
15 | <% issues.each do |issue| -%> | |
16 |
<% if @query.grouped? && (group = |
|
16 | <% if @query.grouped? && (group = @query.group_by_column.value(issue)) != previous_group %> | |
17 | <% reset_cycle %> |
|
17 | <% reset_cycle %> | |
18 | <tr class="group open"> |
|
18 | <tr class="group open"> | |
19 | <td colspan="<%= query.columns.size + 2 %>"> |
|
19 | <td colspan="<%= query.columns.size + 2 %>"> | |
20 | <span class="expander" onclick="toggleRowGroup(this); return false;"> </span> |
|
20 | <span class="expander" onclick="toggleRowGroup(this); return false;"> </span> | |
21 | <%= group.blank? ? 'None' : group %> <span class="count">(<%= @issue_count_by_group[group] %>)</span> |
|
21 | <%= group.blank? ? 'None' : column_content(@query.group_by_column, issue) %> <span class="count">(<%= @issue_count_by_group[group] %>)</span> | |
22 | </td> |
|
22 | </td> | |
23 | </tr> |
|
23 | </tr> | |
24 | <% previous_group = group %> |
|
24 | <% previous_group = group %> |
@@ -101,3 +101,17 custom_fields_007: | |||||
101 | field_format: bool |
|
101 | field_format: bool | |
102 | default_value: "" |
|
102 | default_value: "" | |
103 | editable: true |
|
103 | editable: true | |
|
104 | custom_fields_008: | |||
|
105 | name: Custom date | |||
|
106 | min_length: 0 | |||
|
107 | regexp: "" | |||
|
108 | is_for_all: true | |||
|
109 | is_filter: false | |||
|
110 | type: IssueCustomField | |||
|
111 | max_length: 0 | |||
|
112 | possible_values: "" | |||
|
113 | id: 8 | |||
|
114 | is_required: false | |||
|
115 | field_format: date | |||
|
116 | default_value: "" | |||
|
117 | editable: true |
@@ -95,3 +95,9 custom_values_016: | |||||
95 | customized_id: 11 |
|
95 | customized_id: 11 | |
96 | id: 16 |
|
96 | id: 16 | |
97 | value: '1' |
|
97 | value: '1' | |
|
98 | custom_values_017: | |||
|
99 | customized_type: Issue | |||
|
100 | custom_field_id: 8 | |||
|
101 | customized_id: 1 | |||
|
102 | id: 17 | |||
|
103 | value: '2009-12-01' |
@@ -177,10 +177,7 class IssuesControllerTest < ActionController::TestCase | |||||
177 | assert_response :success |
|
177 | assert_response :success | |
178 | assert_template 'index.rhtml' |
|
178 | assert_template 'index.rhtml' | |
179 | assert_not_nil assigns(:issues) |
|
179 | assert_not_nil assigns(:issues) | |
180 |
|
|
180 | assert_not_nil assigns(:issue_count_by_group) | |
181 | assert_kind_of Hash, count_by_group |
|
|||
182 | assert_kind_of Tracker, count_by_group.keys.first |
|
|||
183 | assert_not_nil count_by_group[Tracker.find(1)] |
|
|||
184 | end |
|
181 | end | |
185 |
|
182 | |||
186 | def test_index_with_query_grouped_by_list_custom_field |
|
183 | def test_index_with_query_grouped_by_list_custom_field | |
@@ -188,10 +185,7 class IssuesControllerTest < ActionController::TestCase | |||||
188 | assert_response :success |
|
185 | assert_response :success | |
189 | assert_template 'index.rhtml' |
|
186 | assert_template 'index.rhtml' | |
190 | assert_not_nil assigns(:issues) |
|
187 | assert_not_nil assigns(:issues) | |
191 |
|
|
188 | assert_not_nil assigns(:issue_count_by_group) | |
192 | assert_kind_of Hash, count_by_group |
|
|||
193 | assert_kind_of String, count_by_group.keys.first |
|
|||
194 | assert_not_nil count_by_group['MySQL'] |
|
|||
195 | end |
|
189 | end | |
196 |
|
190 | |||
197 | def test_index_sort_by_field_not_included_in_columns |
|
191 | def test_index_sort_by_field_not_included_in_columns |
@@ -276,6 +276,32 class QueryTest < ActiveSupport::TestCase | |||||
276 | end |
|
276 | end | |
277 | end |
|
277 | end | |
278 |
|
278 | |||
|
279 | def test_issue_count_by_association_group | |||
|
280 | q = Query.new(:name => '_', :group_by => 'assigned_to') | |||
|
281 | count_by_group = q.issue_count_by_group | |||
|
282 | assert_kind_of Hash, count_by_group | |||
|
283 | assert_equal %w(NilClass User), count_by_group.keys.collect {|k| k.class.name}.uniq.sort | |||
|
284 | assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq | |||
|
285 | assert count_by_group.has_key?(User.find(3)) | |||
|
286 | end | |||
|
287 | ||||
|
288 | def test_issue_count_by_list_custom_field_group | |||
|
289 | q = Query.new(:name => '_', :group_by => 'cf_1') | |||
|
290 | count_by_group = q.issue_count_by_group | |||
|
291 | assert_kind_of Hash, count_by_group | |||
|
292 | assert_equal %w(NilClass String), count_by_group.keys.collect {|k| k.class.name}.uniq.sort | |||
|
293 | assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq | |||
|
294 | assert count_by_group.has_key?('MySQL') | |||
|
295 | end | |||
|
296 | ||||
|
297 | def test_issue_count_by_date_custom_field_group | |||
|
298 | q = Query.new(:name => '_', :group_by => 'cf_8') | |||
|
299 | count_by_group = q.issue_count_by_group | |||
|
300 | assert_kind_of Hash, count_by_group | |||
|
301 | assert_equal %w(Date NilClass), count_by_group.keys.collect {|k| k.class.name}.uniq.sort | |||
|
302 | assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq | |||
|
303 | end | |||
|
304 | ||||
279 | def test_label_for |
|
305 | def test_label_for | |
280 | q = Query.new |
|
306 | q = Query.new | |
281 | assert_equal 'assigned_to', q.label_for('assigned_to_id') |
|
307 | assert_equal 'assigned_to', q.label_for('assigned_to_id') |
General Comments 0
You need to be logged in to leave comments.
Login now