##// END OF EJS Templates
Don't show project column by default when inside a project....
Jean-Philippe Lang -
r15660:af1182c8ba64
parent child
Show More
@@ -1,246 +1,250
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class TimeEntryQuery < Query
19 19
20 20 self.queried_class = TimeEntry
21 21 self.view_permission = :view_time_entries
22 22
23 23 self.available_columns = [
24 24 QueryColumn.new(:project, :sortable => "#{Project.table_name}.name", :groupable => true),
25 25 QueryColumn.new(:spent_on, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"], :default_order => 'desc', :groupable => true),
26 26 QueryColumn.new(:tweek, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"], :caption => l(:label_week)),
27 27 QueryColumn.new(:user, :sortable => lambda {User.fields_for_order_statement}, :groupable => true),
28 28 QueryColumn.new(:activity, :sortable => "#{TimeEntryActivity.table_name}.position", :groupable => true),
29 29 QueryColumn.new(:issue, :sortable => "#{Issue.table_name}.id"),
30 30 QueryAssociationColumn.new(:issue, :tracker, :caption => :field_tracker, :sortable => "#{Tracker.table_name}.position"),
31 31 QueryAssociationColumn.new(:issue, :status, :caption => :field_status, :sortable => "#{IssueStatus.table_name}.position"),
32 32 QueryColumn.new(:comments),
33 33 QueryColumn.new(:hours, :sortable => "#{TimeEntry.table_name}.hours", :totalable => true),
34 34 ]
35 35
36 36 def initialize(attributes=nil, *args)
37 37 super attributes
38 38 self.filters ||= {}
39 39 add_filter('spent_on', '*') unless filters.present?
40 40 end
41 41
42 42 def initialize_available_filters
43 43 add_available_filter "spent_on", :type => :date_past
44 44
45 45 principals = []
46 46 versions = []
47 47 if project
48 48 principals += project.principals.visible.sort
49 49 unless project.leaf?
50 50 subprojects = project.descendants.visible.to_a
51 51 if subprojects.any?
52 52 add_available_filter "subproject_id",
53 53 :type => :list_subprojects,
54 54 :values => subprojects.collect{|s| [s.name, s.id.to_s] }
55 55 principals += Principal.member_of(subprojects).visible
56 56 end
57 57 end
58 58 versions = project.shared_versions.to_a
59 59 else
60 60 if all_projects.any?
61 61 # members of visible projects
62 62 principals += Principal.member_of(all_projects).visible
63 63 # project filter
64 64 project_values = []
65 65 if User.current.logged? && User.current.memberships.any?
66 66 project_values << ["<< #{l(:label_my_projects).downcase} >>", "mine"]
67 67 end
68 68 project_values += all_projects_values
69 69 add_available_filter("project_id",
70 70 :type => :list, :values => project_values
71 71 ) unless project_values.empty?
72 72 end
73 73 end
74 74
75 75 add_available_filter("issue_id", :type => :tree, :label => :label_issue)
76 76 add_available_filter("issue.tracker_id",
77 77 :type => :list,
78 78 :name => l("label_attribute_of_issue", :name => l(:field_tracker)),
79 79 :values => Tracker.sorted.map {|t| [t.name, t.id.to_s]})
80 80 add_available_filter("issue.status_id",
81 81 :type => :list,
82 82 :name => l("label_attribute_of_issue", :name => l(:field_status)),
83 83 :values => IssueStatus.sorted.map {|s| [s.name, s.id.to_s]})
84 84 add_available_filter("issue.fixed_version_id",
85 85 :type => :list,
86 86 :name => l("label_attribute_of_issue", :name => l(:field_fixed_version)),
87 87 :values => Version.sort_by_status(versions).collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s, l("version_status_#{s.status}")] })
88 88
89 89 principals.uniq!
90 90 principals.sort!
91 91 users = principals.select {|p| p.is_a?(User)}
92 92
93 93 users_values = []
94 94 users_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
95 95 users_values += users.collect{|s| [s.name, s.id.to_s] }
96 96 add_available_filter("user_id",
97 97 :type => :list_optional, :values => users_values
98 98 ) unless users_values.empty?
99 99
100 100 activities = (project ? project.activities : TimeEntryActivity.shared)
101 101 add_available_filter("activity_id",
102 102 :type => :list, :values => activities.map {|a| [a.name, a.id.to_s]}
103 103 ) unless activities.empty?
104 104
105 105 add_available_filter "comments", :type => :text
106 106 add_available_filter "hours", :type => :float
107 107
108 108 add_custom_fields_filters(TimeEntryCustomField)
109 109 add_associations_custom_fields_filters :project
110 110 add_custom_fields_filters(issue_custom_fields, :issue)
111 111 add_associations_custom_fields_filters :user
112 112 end
113 113
114 114 def available_columns
115 115 return @available_columns if @available_columns
116 116 @available_columns = self.class.available_columns.dup
117 117 @available_columns += TimeEntryCustomField.visible.
118 118 map {|cf| QueryCustomFieldColumn.new(cf) }
119 119 @available_columns += issue_custom_fields.visible.
120 120 map {|cf| QueryAssociationCustomFieldColumn.new(:issue, cf, :totalable => false) }
121 121 @available_columns
122 122 end
123 123
124 124 def default_columns_names
125 @default_columns_names ||= [:project, :spent_on, :user, :activity, :issue, :comments, :hours]
125 @default_columns_names ||= begin
126 default_columns = [:spent_on, :user, :activity, :issue, :comments, :hours]
127
128 project.present? ? default_columns : [:project] | default_columns
129 end
126 130 end
127 131
128 132 def default_totalable_names
129 133 [:hours]
130 134 end
131 135
132 136 def base_scope
133 137 TimeEntry.visible.
134 138 joins(:project, :user).
135 139 joins("LEFT OUTER JOIN issues ON issues.id = time_entries.issue_id").
136 140 where(statement)
137 141 end
138 142
139 143 def results_scope(options={})
140 144 order_option = [group_by_sort_order, options[:order]].flatten.reject(&:blank?)
141 145
142 146 base_scope.
143 147 order(order_option).
144 148 joins(joins_for_order_statement(order_option.join(','))).
145 149 includes(:activity).
146 150 references(:activity)
147 151 end
148 152
149 153 # Returns sum of all the spent hours
150 154 def total_for_hours(scope)
151 155 map_total(scope.sum(:hours)) {|t| t.to_f.round(2)}
152 156 end
153 157
154 158 def sql_for_issue_id_field(field, operator, value)
155 159 case operator
156 160 when "="
157 161 "#{TimeEntry.table_name}.issue_id = #{value.first.to_i}"
158 162 when "~"
159 163 issue = Issue.where(:id => value.first.to_i).first
160 164 if issue && (issue_ids = issue.self_and_descendants.pluck(:id)).any?
161 165 "#{TimeEntry.table_name}.issue_id IN (#{issue_ids.join(',')})"
162 166 else
163 167 "1=0"
164 168 end
165 169 when "!*"
166 170 "#{TimeEntry.table_name}.issue_id IS NULL"
167 171 when "*"
168 172 "#{TimeEntry.table_name}.issue_id IS NOT NULL"
169 173 end
170 174 end
171 175
172 176 def sql_for_issue_fixed_version_id_field(field, operator, value)
173 177 issue_ids = Issue.where(:fixed_version_id => value.first.to_i).pluck(:id)
174 178 case operator
175 179 when "="
176 180 if issue_ids.any?
177 181 "#{TimeEntry.table_name}.issue_id IN (#{issue_ids.join(',')})"
178 182 else
179 183 "1=0"
180 184 end
181 185 when "!"
182 186 if issue_ids.any?
183 187 "#{TimeEntry.table_name}.issue_id NOT IN (#{issue_ids.join(',')})"
184 188 else
185 189 "1=1"
186 190 end
187 191 end
188 192 end
189 193
190 194 def sql_for_activity_id_field(field, operator, value)
191 195 condition_on_id = sql_for_field(field, operator, value, Enumeration.table_name, 'id')
192 196 condition_on_parent_id = sql_for_field(field, operator, value, Enumeration.table_name, 'parent_id')
193 197 ids = value.map(&:to_i).join(',')
194 198 table_name = Enumeration.table_name
195 199 if operator == '='
196 200 "(#{table_name}.id IN (#{ids}) OR #{table_name}.parent_id IN (#{ids}))"
197 201 else
198 202 "(#{table_name}.id NOT IN (#{ids}) AND (#{table_name}.parent_id IS NULL OR #{table_name}.parent_id NOT IN (#{ids})))"
199 203 end
200 204 end
201 205
202 206 def sql_for_issue_tracker_id_field(field, operator, value)
203 207 sql_for_field("tracker_id", operator, value, Issue.table_name, "tracker_id")
204 208 end
205 209
206 210 def sql_for_issue_status_id_field(field, operator, value)
207 211 sql_for_field("status_id", operator, value, Issue.table_name, "status_id")
208 212 end
209 213
210 214 # Accepts :from/:to params as shortcut filters
211 215 def build_from_params(params)
212 216 super
213 217 if params[:from].present? && params[:to].present?
214 218 add_filter('spent_on', '><', [params[:from], params[:to]])
215 219 elsif params[:from].present?
216 220 add_filter('spent_on', '>=', [params[:from]])
217 221 elsif params[:to].present?
218 222 add_filter('spent_on', '<=', [params[:to]])
219 223 end
220 224 self
221 225 end
222 226
223 227 def joins_for_order_statement(order_options)
224 228 joins = [super]
225 229
226 230 if order_options
227 231 if order_options.include?('issue_statuses')
228 232 joins << "LEFT OUTER JOIN #{IssueStatus.table_name} ON #{IssueStatus.table_name}.id = #{Issue.table_name}.status_id"
229 233 end
230 234 if order_options.include?('trackers')
231 235 joins << "LEFT OUTER JOIN #{Tracker.table_name} ON #{Tracker.table_name}.id = #{Issue.table_name}.tracker_id"
232 236 end
233 237 end
234 238
235 239 joins.compact!
236 240 joins.any? ? joins.join(' ') : nil
237 241 end
238 242
239 243 def issue_custom_fields
240 244 if project
241 245 project.all_issue_custom_fields
242 246 else
243 247 IssueCustomField.where(:is_for_all => true)
244 248 end
245 249 end
246 250 end
General Comments 0
You need to be logged in to leave comments. Login now