@@ -24,28 +24,7 module QueriesHelper | |||
|
24 | 24 | |
|
25 | 25 | def filters_options(query) |
|
26 | 26 | options = [[]] |
|
27 |
|
|
|
28 | ord = 0 | |
|
29 | if !(a[1][:order] == 20 && b[1][:order] == 20) | |
|
30 | ord = a[1][:order] <=> b[1][:order] | |
|
31 | else | |
|
32 | cn = (CustomField::CUSTOM_FIELDS_NAMES.index(a[1][:field].class.name) <=> | |
|
33 | CustomField::CUSTOM_FIELDS_NAMES.index(b[1][:field].class.name)) | |
|
34 | if cn != 0 | |
|
35 | ord = cn | |
|
36 | else | |
|
37 | f = (a[1][:field] <=> b[1][:field]) | |
|
38 | if f != 0 | |
|
39 | ord = f | |
|
40 | else | |
|
41 | # assigned_to or author | |
|
42 | ord = (a[0] <=> b[0]) | |
|
43 | end | |
|
44 | end | |
|
45 | end | |
|
46 | ord | |
|
47 | end | |
|
48 | options += sorted_options.map do |field, field_options| | |
|
27 | options += query.available_filters.map do |field, field_options| | |
|
49 | 28 | [field_options[:name], field] |
|
50 | 29 | end |
|
51 | 30 | end |
@@ -58,141 +58,127 class IssueQuery < Query | |||
|
58 | 58 | (project.nil? || user.allowed_to?(:view_issues, project)) && (self.is_public? || self.user_id == user.id) |
|
59 | 59 | end |
|
60 | 60 | |
|
61 | def available_filters | |
|
62 | return @available_filters if @available_filters | |
|
63 | @available_filters = { | |
|
64 | "status_id" => { | |
|
65 | :type => :list_status, :order => 0, | |
|
66 | :values => IssueStatus.sorted.all.collect{|s| [s.name, s.id.to_s] } | |
|
67 | }, | |
|
68 | "tracker_id" => { | |
|
69 | :type => :list, :order => 2, :values => trackers.collect{|s| [s.name, s.id.to_s] } | |
|
70 | }, | |
|
71 | "priority_id" => { | |
|
72 | :type => :list, :order => 3, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s] } | |
|
73 | }, | |
|
74 | "subject" => { :type => :text, :order => 8 }, | |
|
75 | "created_on" => { :type => :date_past, :order => 9 }, | |
|
76 | "updated_on" => { :type => :date_past, :order => 10 }, | |
|
77 | "start_date" => { :type => :date, :order => 11 }, | |
|
78 | "due_date" => { :type => :date, :order => 12 }, | |
|
79 | "estimated_hours" => { :type => :float, :order => 13 }, | |
|
80 | "done_ratio" => { :type => :integer, :order => 14 } | |
|
81 | } | |
|
82 | IssueRelation::TYPES.each do |relation_type, options| | |
|
83 | @available_filters[relation_type] = { | |
|
84 | :type => :relation, :order => @available_filters.size + 100, | |
|
85 | :label => options[:name] | |
|
86 | } | |
|
87 | end | |
|
61 | def initialize_available_filters | |
|
88 | 62 | principals = [] |
|
63 | subprojects = [] | |
|
64 | versions = [] | |
|
65 | categories = [] | |
|
66 | issue_custom_fields = [] | |
|
67 | ||
|
89 | 68 | if project |
|
90 | 69 | principals += project.principals.sort |
|
91 | 70 | unless project.leaf? |
|
92 | 71 | subprojects = project.descendants.visible.all |
|
93 | if subprojects.any? | |
|
94 | @available_filters["subproject_id"] = { | |
|
95 | :type => :list_subprojects, :order => 13, | |
|
96 | :values => subprojects.collect{|s| [s.name, s.id.to_s] } | |
|
97 | } | |
|
98 | principals += Principal.member_of(subprojects) | |
|
99 | end | |
|
72 | principals += Principal.member_of(subprojects) | |
|
100 | 73 | end |
|
74 | versions = project.shared_versions.all | |
|
75 | categories = project.issue_categories.all | |
|
76 | issue_custom_fields = project.all_issue_custom_fields | |
|
101 | 77 | else |
|
102 | 78 | if all_projects.any? |
|
103 | # members of visible projects | |
|
104 | 79 | principals += Principal.member_of(all_projects) |
|
105 | # project filter | |
|
106 | project_values = [] | |
|
107 | if User.current.logged? && User.current.memberships.any? | |
|
108 | project_values << ["<< #{l(:label_my_projects).downcase} >>", "mine"] | |
|
109 | end | |
|
110 | project_values += all_projects_values | |
|
111 | @available_filters["project_id"] = { | |
|
112 | :type => :list, :order => 1, :values => project_values | |
|
113 | } unless project_values.empty? | |
|
114 | 80 | end |
|
81 | versions = Version.visible.find_all_by_sharing('system') | |
|
82 | issue_custom_fields = IssueCustomField.where(:is_filter => true, :is_for_all => true).all | |
|
115 | 83 | end |
|
116 | 84 | principals.uniq! |
|
117 | 85 | principals.sort! |
|
118 | 86 | users = principals.select {|p| p.is_a?(User)} |
|
119 | 87 | |
|
120 | assigned_to_values = [] | |
|
121 | assigned_to_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? | |
|
122 | assigned_to_values += (Setting.issue_group_assignment? ? | |
|
123 | principals : users).collect{|s| [s.name, s.id.to_s] } | |
|
124 | @available_filters["assigned_to_id"] = { | |
|
125 | :type => :list_optional, :order => 4, :values => assigned_to_values | |
|
126 | } unless assigned_to_values.empty? | |
|
88 | ||
|
89 | add_available_filter "status_id", | |
|
90 | :type => :list_status, :values => IssueStatus.sorted.all.collect{|s| [s.name, s.id.to_s] } | |
|
91 | ||
|
92 | if project.nil? | |
|
93 | project_values = [] | |
|
94 | if User.current.logged? && User.current.memberships.any? | |
|
95 | project_values << ["<< #{l(:label_my_projects).downcase} >>", "mine"] | |
|
96 | end | |
|
97 | project_values += all_projects_values | |
|
98 | add_available_filter("project_id", | |
|
99 | :type => :list, :values => project_values | |
|
100 | ) unless project_values.empty? | |
|
101 | end | |
|
102 | ||
|
103 | add_available_filter "tracker_id", | |
|
104 | :type => :list, :values => trackers.collect{|s| [s.name, s.id.to_s] } | |
|
105 | add_available_filter "priority_id", | |
|
106 | :type => :list, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s] } | |
|
127 | 107 | |
|
128 | 108 | author_values = [] |
|
129 | 109 | author_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? |
|
130 | 110 | author_values += users.collect{|s| [s.name, s.id.to_s] } |
|
131 |
|
|
|
132 |
:type => :list, |
|
|
133 |
|
|
|
111 | add_available_filter("author_id", | |
|
112 | :type => :list, :values => author_values | |
|
113 | ) unless author_values.empty? | |
|
114 | ||
|
115 | assigned_to_values = [] | |
|
116 | assigned_to_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? | |
|
117 | assigned_to_values += (Setting.issue_group_assignment? ? | |
|
118 | principals : users).collect{|s| [s.name, s.id.to_s] } | |
|
119 | add_available_filter("assigned_to_id", | |
|
120 | :type => :list_optional, :values => assigned_to_values | |
|
121 | ) unless assigned_to_values.empty? | |
|
134 | 122 | |
|
135 | 123 | group_values = Group.all.collect {|g| [g.name, g.id.to_s] } |
|
136 |
|
|
|
137 |
:type => :list_optional, |
|
|
138 |
|
|
|
124 | add_available_filter("member_of_group", | |
|
125 | :type => :list_optional, :values => group_values | |
|
126 | ) unless group_values.empty? | |
|
139 | 127 | |
|
140 | 128 | role_values = Role.givable.collect {|r| [r.name, r.id.to_s] } |
|
141 |
|
|
|
142 |
:type => :list_optional, |
|
|
143 |
|
|
|
144 | ||
|
145 | if User.current.logged? | |
|
146 |
|
|
|
147 | :type => :list, :order => 15, :values => [["<< #{l(:label_me)} >>", "me"]] | |
|
148 | } | |
|
129 | add_available_filter("assigned_to_role", | |
|
130 | :type => :list_optional, :values => role_values | |
|
131 | ) unless role_values.empty? | |
|
132 | ||
|
133 | if versions.any? | |
|
134 | add_available_filter "fixed_version_id", | |
|
135 | :type => :list_optional, | |
|
136 | :values => versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } | |
|
149 | 137 | end |
|
150 | 138 | |
|
151 | if project | |
|
152 | # project specific filters | |
|
153 | categories = project.issue_categories.all | |
|
154 | unless categories.empty? | |
|
155 | @available_filters["category_id"] = { | |
|
156 | :type => :list_optional, :order => 6, | |
|
157 | :values => categories.collect{|s| [s.name, s.id.to_s] } | |
|
158 | } | |
|
159 | end | |
|
160 | versions = project.shared_versions.all | |
|
161 | unless versions.empty? | |
|
162 | @available_filters["fixed_version_id"] = { | |
|
163 | :type => :list_optional, :order => 7, | |
|
164 | :values => versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } | |
|
165 | } | |
|
166 | end | |
|
167 | add_custom_fields_filters(project.all_issue_custom_fields) | |
|
168 | else | |
|
169 | # global filters for cross project issue list | |
|
170 | system_shared_versions = Version.visible.find_all_by_sharing('system') | |
|
171 | unless system_shared_versions.empty? | |
|
172 | @available_filters["fixed_version_id"] = { | |
|
173 | :type => :list_optional, :order => 7, | |
|
174 | :values => system_shared_versions.sort.collect{|s| | |
|
175 | ["#{s.project.name} - #{s.name}", s.id.to_s] | |
|
176 | } | |
|
177 | } | |
|
178 | end | |
|
179 | add_custom_fields_filters(IssueCustomField.where(:is_filter => true, :is_for_all => true).all) | |
|
139 | if categories.any? | |
|
140 | add_available_filter "category_id", | |
|
141 | :type => :list_optional, | |
|
142 | :values => categories.collect{|s| [s.name, s.id.to_s] } | |
|
180 | 143 | end |
|
181 | add_associations_custom_fields_filters :project, :author, :assigned_to, :fixed_version | |
|
144 | ||
|
145 | add_available_filter "subject", :type => :text | |
|
146 | add_available_filter "created_on", :type => :date_past | |
|
147 | add_available_filter "updated_on", :type => :date_past | |
|
148 | add_available_filter "start_date", :type => :date | |
|
149 | add_available_filter "due_date", :type => :date | |
|
150 | add_available_filter "estimated_hours", :type => :float | |
|
151 | add_available_filter "done_ratio", :type => :integer | |
|
152 | ||
|
182 | 153 | if User.current.allowed_to?(:set_issues_private, nil, :global => true) || |
|
183 | 154 | User.current.allowed_to?(:set_own_issues_private, nil, :global => true) |
|
184 |
|
|
|
185 |
:type => :list, |
|
|
155 | add_available_filter "is_private", | |
|
156 | :type => :list, | |
|
186 | 157 | :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]] |
|
187 | } | |
|
188 | 158 | end |
|
159 | ||
|
160 | if User.current.logged? | |
|
161 | add_available_filter "watcher_id", | |
|
162 | :type => :list, :values => [["<< #{l(:label_me)} >>", "me"]] | |
|
163 | end | |
|
164 | ||
|
165 | if subprojects.any? | |
|
166 | add_available_filter "subproject_id", | |
|
167 | :type => :list_subprojects, | |
|
168 | :values => subprojects.collect{|s| [s.name, s.id.to_s] } | |
|
169 | end | |
|
170 | ||
|
171 | add_custom_fields_filters(issue_custom_fields) | |
|
172 | ||
|
173 | add_associations_custom_fields_filters :project, :author, :assigned_to, :fixed_version | |
|
174 | ||
|
175 | IssueRelation::TYPES.each do |relation_type, options| | |
|
176 | add_available_filter relation_type, :type => :relation, :label => options[:name] | |
|
177 | end | |
|
178 | ||
|
189 | 179 | Tracker.disabled_core_fields(trackers).each {|field| |
|
190 |
|
|
|
180 | delete_available_filter field | |
|
191 | 181 | } |
|
192 | @available_filters.each do |field, options| | |
|
193 | options[:name] ||= l(options[:label] || "field_#{field}".gsub(/_id$/, '')) | |
|
194 | end | |
|
195 | @available_filters | |
|
196 | 182 | end |
|
197 | 183 | |
|
198 | 184 | def available_columns |
@@ -278,6 +278,37 class Query < ActiveRecord::Base | |||
|
278 | 278 | @all_projects_values = values |
|
279 | 279 | end |
|
280 | 280 | |
|
281 | # Adds available filters | |
|
282 | def initialize_available_filters | |
|
283 | # implemented by sub-classes | |
|
284 | end | |
|
285 | protected :initialize_available_filters | |
|
286 | ||
|
287 | # Adds an available filter | |
|
288 | def add_available_filter(field, options) | |
|
289 | @available_filters ||= ActiveSupport::OrderedHash.new | |
|
290 | @available_filters[field] = options | |
|
291 | @available_filters | |
|
292 | end | |
|
293 | ||
|
294 | # Removes an available filter | |
|
295 | def delete_available_filter(field) | |
|
296 | if @available_filters | |
|
297 | @available_filters.delete(field) | |
|
298 | end | |
|
299 | end | |
|
300 | ||
|
301 | # Return a hash of available filters | |
|
302 | def available_filters | |
|
303 | unless @available_filters | |
|
304 | initialize_available_filters | |
|
305 | @available_filters.each do |field, options| | |
|
306 | options[:name] ||= l(options[:label] || "field_#{field}".gsub(/_id$/, '')) | |
|
307 | end | |
|
308 | end | |
|
309 | @available_filters | |
|
310 | end | |
|
311 | ||
|
281 | 312 | def add_filter(field, operator, values=nil) |
|
282 | 313 | # values must be an array |
|
283 | 314 | return unless values.nil? || values.is_a?(Array) |
@@ -692,31 +723,30 class Query < ActiveRecord::Base | |||
|
692 | 723 | |
|
693 | 724 | def add_custom_fields_filters(custom_fields, assoc=nil) |
|
694 | 725 | return unless custom_fields.present? |
|
695 | @available_filters ||= {} | |
|
696 | 726 | |
|
697 | custom_fields.select(&:is_filter?).each do |field| | |
|
727 | custom_fields.select(&:is_filter?).sort.each do |field| | |
|
698 | 728 | case field.field_format |
|
699 | 729 | when "text" |
|
700 |
options = { :type => :text |
|
|
730 | options = { :type => :text } | |
|
701 | 731 | when "list" |
|
702 |
options = { :type => :list_optional, :values => field.possible_values |
|
|
732 | options = { :type => :list_optional, :values => field.possible_values } | |
|
703 | 733 | when "date" |
|
704 |
options = { :type => :date |
|
|
734 | options = { :type => :date } | |
|
705 | 735 | when "bool" |
|
706 |
options = { :type => :list, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]] |
|
|
736 | options = { :type => :list, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]] } | |
|
707 | 737 | when "int" |
|
708 |
options = { :type => :integer |
|
|
738 | options = { :type => :integer } | |
|
709 | 739 | when "float" |
|
710 |
options = { :type => :float |
|
|
740 | options = { :type => :float } | |
|
711 | 741 | when "user", "version" |
|
712 | 742 | next unless project |
|
713 | 743 | values = field.possible_values_options(project) |
|
714 | 744 | if User.current.logged? && field.field_format == 'user' |
|
715 | 745 | values.unshift ["<< #{l(:label_me)} >>", "me"] |
|
716 | 746 | end |
|
717 |
options = { :type => :list_optional, :values => values |
|
|
747 | options = { :type => :list_optional, :values => values } | |
|
718 | 748 | else |
|
719 |
options = { :type => :string |
|
|
749 | options = { :type => :string } | |
|
720 | 750 | end |
|
721 | 751 | filter_id = "cf_#{field.id}" |
|
722 | 752 | filter_name = field.name |
@@ -724,7 +754,7 class Query < ActiveRecord::Base | |||
|
724 | 754 | filter_id = "#{assoc}.#{filter_id}" |
|
725 | 755 | filter_name = l("label_attribute_of_#{assoc}", :name => filter_name) |
|
726 | 756 | end |
|
727 |
|
|
|
757 | add_available_filter filter_id, options.merge({ | |
|
728 | 758 | :name => filter_name, |
|
729 | 759 | :format => field.field_format, |
|
730 | 760 | :field => field |
@@ -35,13 +35,8 class TimeEntryQuery < Query | |||
|
35 | 35 | add_filter('spent_on', '*') unless filters.present? |
|
36 | 36 | end |
|
37 | 37 | |
|
38 | def available_filters | |
|
39 | return @available_filters if @available_filters | |
|
40 | @available_filters = { | |
|
41 | "spent_on" => { :type => :date_past, :order => 0 }, | |
|
42 | "comments" => { :type => :text, :order => 5 }, | |
|
43 | "hours" => { :type => :float, :order => 6 } | |
|
44 | } | |
|
38 | def initialize_available_filters | |
|
39 | add_available_filter "spent_on", :type => :date_past | |
|
45 | 40 | |
|
46 | 41 | principals = [] |
|
47 | 42 | if project |
@@ -49,10 +44,9 class TimeEntryQuery < Query | |||
|
49 | 44 | unless project.leaf? |
|
50 | 45 | subprojects = project.descendants.visible.all |
|
51 | 46 | if subprojects.any? |
|
52 |
|
|
|
53 |
:type => :list_subprojects, |
|
|
47 | add_available_filter "subproject_id", | |
|
48 | :type => :list_subprojects, | |
|
54 | 49 | :values => subprojects.collect{|s| [s.name, s.id.to_s] } |
|
55 | } | |
|
56 | 50 | principals += Principal.member_of(subprojects) |
|
57 | 51 | end |
|
58 | 52 | end |
@@ -66,9 +60,9 class TimeEntryQuery < Query | |||
|
66 | 60 | project_values << ["<< #{l(:label_my_projects).downcase} >>", "mine"] |
|
67 | 61 | end |
|
68 | 62 | project_values += all_projects_values |
|
69 |
|
|
|
70 |
:type => :list, |
|
|
71 |
|
|
|
63 | add_available_filter("project_id", | |
|
64 | :type => :list, :values => project_values | |
|
65 | ) unless project_values.empty? | |
|
72 | 66 | end |
|
73 | 67 | end |
|
74 | 68 | principals.uniq! |
@@ -78,22 +72,20 class TimeEntryQuery < Query | |||
|
78 | 72 | users_values = [] |
|
79 | 73 | users_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? |
|
80 | 74 | users_values += users.collect{|s| [s.name, s.id.to_s] } |
|
81 |
|
|
|
82 |
:type => :list_optional, |
|
|
83 |
|
|
|
75 | add_available_filter("user_id", | |
|
76 | :type => :list_optional, :values => users_values | |
|
77 | ) unless users_values.empty? | |
|
84 | 78 | |
|
85 | 79 | activities = (project ? project.activities : TimeEntryActivity.shared.active) |
|
86 |
|
|
|
87 |
:type => :list |
|
|
88 |
|
|
|
80 | add_available_filter("activity_id", | |
|
81 | :type => :list, :values => activities.map {|a| [a.name, a.id.to_s]} | |
|
82 | ) unless activities.empty? | |
|
83 | ||
|
84 | add_available_filter "comments", :type => :text | |
|
85 | add_available_filter "hours", :type => :float | |
|
89 | 86 | |
|
90 | 87 | add_custom_fields_filters(TimeEntryCustomField.where(:is_filter => true).all) |
|
91 | 88 | add_associations_custom_fields_filters :project, :issue, :user |
|
92 | ||
|
93 | @available_filters.each do |field, options| | |
|
94 | options[:name] ||= l(options[:label] || "field_#{field}".gsub(/_id$/, '')) | |
|
95 | end | |
|
96 | @available_filters | |
|
97 | 89 | end |
|
98 | 90 | |
|
99 | 91 | def available_columns |
@@ -29,7 +29,7 class QueriesHelperTest < ActionView::TestCase | |||
|
29 | 29 | :projects_trackers, |
|
30 | 30 | :custom_fields_trackers |
|
31 | 31 | |
|
32 | def test_order | |
|
32 | def test_filters_options_should_be_ordered | |
|
33 | 33 | User.current = User.find_by_login('admin') |
|
34 | 34 | query = IssueQuery.new(:project => nil, :name => '_') |
|
35 | 35 | assert_equal 30, query.available_filters.size |
@@ -40,17 +40,16 class QueriesHelperTest < ActionView::TestCase | |||
|
40 | 40 | assert_equal "project_id", fo[2][1] |
|
41 | 41 | assert_equal "tracker_id", fo[3][1] |
|
42 | 42 | assert_equal "priority_id", fo[4][1] |
|
43 |
assert_equal " |
|
|
44 |
assert_equal " |
|
|
43 | assert_equal "is_private", fo[17][1] | |
|
44 | assert_equal "watcher_id", fo[18][1] | |
|
45 | 45 | end |
|
46 | 46 | |
|
47 | def test_order_custom_fields | |
|
47 | def test_filters_options_should_be_ordered_with_custom_fields | |
|
48 | 48 | set_language_if_valid 'en' |
|
49 |
field = UserCustomField. |
|
|
49 | field = UserCustomField.create!( | |
|
50 | 50 | :name => 'order test', :field_format => 'string', |
|
51 | 51 | :is_for_all => true, :is_filter => true |
|
52 | 52 | ) |
|
53 | assert field.save | |
|
54 | 53 | User.current = User.find_by_login('admin') |
|
55 | 54 | query = IssueQuery.new(:project => nil, :name => '_') |
|
56 | 55 | assert_equal 32, query.available_filters.size |
@@ -59,7 +58,7 class QueriesHelperTest < ActionView::TestCase | |||
|
59 | 58 | assert_equal "Searchable field", fo[19][0] |
|
60 | 59 | assert_equal "Database", fo[20][0] |
|
61 | 60 | assert_equal "Project's Development status", fo[21][0] |
|
62 |
assert_equal "A |
|
|
63 |
assert_equal "A |
|
|
61 | assert_equal "Author's order test", fo[22][0] | |
|
62 | assert_equal "Assignee's order test", fo[23][0] | |
|
64 | 63 | end |
|
65 | 64 | end |
@@ -28,6 +28,11 class QueryTest < ActiveSupport::TestCase | |||
|
28 | 28 | :projects_trackers, |
|
29 | 29 | :custom_fields_trackers |
|
30 | 30 | |
|
31 | def test_available_filters_should_be_ordered | |
|
32 | query = IssueQuery.new | |
|
33 | assert_equal 0, query.available_filters.keys.index('status_id') | |
|
34 | end | |
|
35 | ||
|
31 | 36 | def test_custom_fields_for_all_projects_should_be_available_in_global_queries |
|
32 | 37 | query = IssueQuery.new(:project => nil, :name => '_') |
|
33 | 38 | assert query.available_filters.has_key?('cf_1') |
General Comments 0
You need to be logged in to leave comments.
Login now