##// END OF EJS Templates
Ability to sort the issue list by text, int and float custom fields (#1139)....
Jean-Philippe Lang -
r2256:da01ee7c37f2
parent child
Show More
@@ -65,12 +65,20 class CustomField < ActiveRecord::Base
65 # Returns false, if the custom field can not be used for sorting.
65 # Returns false, if the custom field can not be used for sorting.
66 def order_statement
66 def order_statement
67 case field_format
67 case field_format
68 when 'string', 'list', 'date', 'bool'
68 when 'string', 'text', 'list', 'date', 'bool'
69 # COALESCE is here to make sure that blank and NULL values are sorted equally
69 # COALESCE is here to make sure that blank and NULL values are sorted equally
70 "COALESCE((SELECT cv_sort.value FROM #{CustomValue.table_name} cv_sort" +
70 "COALESCE((SELECT cv_sort.value FROM #{CustomValue.table_name} cv_sort" +
71 " WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" +
71 " WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" +
72 " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
72 " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
73 " AND cv_sort.custom_field_id=#{id} LIMIT 1), '')"
73 " AND cv_sort.custom_field_id=#{id} LIMIT 1), '')"
74 when 'int', 'float'
75 # Make the database cast values into numeric
76 # Postgresql will raise an error if a value can not be casted!
77 # CustomValue validations should ensure that it doesn't occur
78 "(SELECT CAST(cv_sort.value AS decimal(60,3)) FROM #{CustomValue.table_name} cv_sort" +
79 " WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" +
80 " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
81 " AND cv_sort.custom_field_id=#{id} AND cv_sort.value <> '' AND cv_sort.value IS NOT NULL LIMIT 1)"
74 else
82 else
75 nil
83 nil
76 end
84 end
@@ -69,4 +69,16 custom_fields_005:
69 is_required: false
69 is_required: false
70 field_format: float
70 field_format: float
71 default_value: ""
71 default_value: ""
72 custom_fields_006:
73 name: Float field
74 min_length: 0
75 regexp: ""
76 is_for_all: true
77 type: IssueCustomField
78 max_length: 0
79 possible_values: ""
80 id: 6
81 is_required: false
82 field_format: float
83 default_value: ""
72 No newline at end of file
84
@@ -8,3 +8,12 custom_fields_trackers_002:
8 custom_fields_trackers_003:
8 custom_fields_trackers_003:
9 custom_field_id: 2
9 custom_field_id: 2
10 tracker_id: 3
10 tracker_id: 3
11 custom_fields_trackers_004:
12 custom_field_id: 6
13 tracker_id: 1
14 custom_fields_trackers_005:
15 custom_field_id: 6
16 tracker_id: 2
17 custom_fields_trackers_006:
18 custom_field_id: 6
19 tracker_id: 3
@@ -3,54 +3,84 custom_values_006:
3 customized_type: Issue
3 customized_type: Issue
4 custom_field_id: 2
4 custom_field_id: 2
5 customized_id: 3
5 customized_id: 3
6 id: 9
6 id: 6
7 value: "125"
7 value: "125"
8 custom_values_007:
8 custom_values_007:
9 customized_type: Project
9 customized_type: Project
10 custom_field_id: 3
10 custom_field_id: 3
11 customized_id: 1
11 customized_id: 1
12 id: 10
12 id: 7
13 value: Stable
13 value: Stable
14 custom_values_001:
14 custom_values_001:
15 customized_type: User
15 customized_type: User
16 custom_field_id: 4
16 custom_field_id: 4
17 customized_id: 3
17 customized_id: 3
18 id: 2
18 id: 1
19 value: ""
19 value: ""
20 custom_values_002:
20 custom_values_002:
21 customized_type: User
21 customized_type: User
22 custom_field_id: 4
22 custom_field_id: 4
23 customized_id: 4
23 customized_id: 4
24 id: 3
24 id: 2
25 value: 01 23 45 67 89
25 value: 01 23 45 67 89
26 custom_values_003:
26 custom_values_003:
27 customized_type: User
27 customized_type: User
28 custom_field_id: 4
28 custom_field_id: 4
29 customized_id: 2
29 customized_id: 2
30 id: 4
30 id: 3
31 value: ""
31 value: ""
32 custom_values_004:
32 custom_values_004:
33 customized_type: Issue
33 customized_type: Issue
34 custom_field_id: 2
34 custom_field_id: 2
35 customized_id: 1
35 customized_id: 1
36 id: 7
36 id: 4
37 value: "125"
37 value: "125"
38 custom_values_005:
38 custom_values_005:
39 customized_type: Issue
39 customized_type: Issue
40 custom_field_id: 2
40 custom_field_id: 2
41 customized_id: 2
41 customized_id: 2
42 id: 8
42 id: 5
43 value: ""
43 value: ""
44 custom_values_008:
44 custom_values_008:
45 customized_type: Issue
45 customized_type: Issue
46 custom_field_id: 1
46 custom_field_id: 1
47 customized_id: 3
47 customized_id: 3
48 id: 11
48 id: 8
49 value: "MySQL"
49 value: "MySQL"
50 custom_values_009:
50 custom_values_009:
51 customized_type: Issue
51 customized_type: Issue
52 custom_field_id: 2
52 custom_field_id: 2
53 customized_id: 3
53 customized_id: 3
54 id: 12
54 id: 9
55 value: "this is a stringforcustomfield search"
55 value: "this is a stringforcustomfield search"
56 custom_values_010:
57 customized_type: Issue
58 custom_field_id: 6
59 customized_id: 1
60 id: 10
61 value: "2.1"
62 custom_values_011:
63 customized_type: Issue
64 custom_field_id: 6
65 customized_id: 2
66 id: 11
67 value: "2.05"
68 custom_values_012:
69 customized_type: Issue
70 custom_field_id: 6
71 customized_id: 3
72 id: 12
73 value: "11.65"
74 custom_values_013:
75 customized_type: Issue
76 custom_field_id: 6
77 customized_id: 7
78 id: 13
79 value: ""
80 custom_values_014:
81 customized_type: Issue
82 custom_field_id: 6
83 customized_id: 5
84 id: 14
85 value: "-7.6"
56 No newline at end of file
86
@@ -185,6 +185,7 class QueryTest < Test::Unit::TestCase
185 :conditions => q.statement,
185 :conditions => q.statement,
186 :order => "#{c.sortable} ASC"
186 :order => "#{c.sortable} ASC"
187 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
187 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
188 assert !values.empty?
188 assert_equal values.sort, values
189 assert_equal values.sort, values
189 end
190 end
190
191
@@ -198,9 +199,24 class QueryTest < Test::Unit::TestCase
198 :conditions => q.statement,
199 :conditions => q.statement,
199 :order => "#{c.sortable} DESC"
200 :order => "#{c.sortable} DESC"
200 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
201 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
202 assert !values.empty?
201 assert_equal values.sort.reverse, values
203 assert_equal values.sort.reverse, values
202 end
204 end
203
205
206 def test_sort_by_float_custom_field_asc
207 q = Query.new
208 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' }
209 assert c
210 assert c.sortable
211 issues = Issue.find :all,
212 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
213 :conditions => q.statement,
214 :order => "#{c.sortable} ASC"
215 values = issues.collect {|i| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact
216 assert !values.empty?
217 assert_equal values.sort, values
218 end
219
204 def test_label_for
220 def test_label_for
205 q = Query.new
221 q = Query.new
206 assert_equal 'assigned_to', q.label_for('assigned_to_id')
222 assert_equal 'assigned_to', q.label_for('assigned_to_id')
General Comments 0
You need to be logged in to leave comments. Login now