##// END OF EJS Templates
Preload project and user....
Jean-Philippe Lang -
r15559:f7782c46480f
parent child
Show More
@@ -1,278 +1,279
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 TimelogController < ApplicationController
19 19 menu_item :time_entries
20 20
21 21 before_action :find_time_entry, :only => [:show, :edit, :update]
22 22 before_action :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy]
23 23 before_action :authorize, :only => [:show, :edit, :update, :bulk_edit, :bulk_update, :destroy]
24 24
25 25 before_action :find_optional_issue, :only => [:new, :create]
26 26 before_action :find_optional_project, :only => [:index, :report]
27 27 before_action :authorize_global, :only => [:new, :create, :index, :report]
28 28
29 29 accept_rss_auth :index
30 30 accept_api_auth :index, :show, :create, :update, :destroy
31 31
32 32 rescue_from Query::StatementInvalid, :with => :query_statement_invalid
33 33
34 34 helper :sort
35 35 include SortHelper
36 36 helper :issues
37 37 include TimelogHelper
38 38 helper :custom_fields
39 39 include CustomFieldsHelper
40 40 helper :queries
41 41 include QueriesHelper
42 42
43 43 def index
44 44 retrieve_time_entry_query
45 45 sort_init(@query.sort_criteria.empty? ? [['spent_on', 'desc']] : @query.sort_criteria)
46 46 sort_update(@query.sortable_columns)
47 47 scope = time_entry_scope(:order => sort_clause).
48 preload(:issue => [:project, :tracker, :status, :assigned_to, :priority])
48 preload(:issue => [:project, :tracker, :status, :assigned_to, :priority]).
49 preload(:project, :user)
49 50
50 51 respond_to do |format|
51 52 format.html {
52 53 @entry_count = scope.count
53 54 @entry_pages = Paginator.new @entry_count, per_page_option, params['page']
54 55 @entries = scope.offset(@entry_pages.offset).limit(@entry_pages.per_page).to_a
55 56
56 57 render :layout => !request.xhr?
57 58 }
58 59 format.api {
59 60 @entry_count = scope.count
60 61 @offset, @limit = api_offset_and_limit
61 62 @entries = scope.offset(@offset).limit(@limit).preload(:custom_values => :custom_field).to_a
62 63 }
63 64 format.atom {
64 65 entries = scope.limit(Setting.feeds_limit.to_i).reorder("#{TimeEntry.table_name}.created_on DESC").to_a
65 66 render_feed(entries, :title => l(:label_spent_time))
66 67 }
67 68 format.csv {
68 69 # Export all entries
69 70 @entries = scope.to_a
70 71 send_data(query_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'timelog.csv')
71 72 }
72 73 end
73 74 end
74 75
75 76 def report
76 77 retrieve_time_entry_query
77 78 scope = time_entry_scope
78 79
79 80 @report = Redmine::Helpers::TimeReport.new(@project, @issue, params[:criteria], params[:columns], scope)
80 81
81 82 respond_to do |format|
82 83 format.html { render :layout => !request.xhr? }
83 84 format.csv { send_data(report_to_csv(@report), :type => 'text/csv; header=present', :filename => 'timelog.csv') }
84 85 end
85 86 end
86 87
87 88 def show
88 89 respond_to do |format|
89 90 # TODO: Implement html response
90 91 format.html { head 406 }
91 92 format.api
92 93 end
93 94 end
94 95
95 96 def new
96 97 @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
97 98 @time_entry.safe_attributes = params[:time_entry]
98 99 end
99 100
100 101 def create
101 102 @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
102 103 @time_entry.safe_attributes = params[:time_entry]
103 104 if @time_entry.project && !User.current.allowed_to?(:log_time, @time_entry.project)
104 105 render_403
105 106 return
106 107 end
107 108
108 109 call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
109 110
110 111 if @time_entry.save
111 112 respond_to do |format|
112 113 format.html {
113 114 flash[:notice] = l(:notice_successful_create)
114 115 if params[:continue]
115 116 options = {
116 117 :time_entry => {
117 118 :project_id => params[:time_entry][:project_id],
118 119 :issue_id => @time_entry.issue_id,
119 120 :activity_id => @time_entry.activity_id
120 121 },
121 122 :back_url => params[:back_url]
122 123 }
123 124 if params[:project_id] && @time_entry.project
124 125 redirect_to new_project_time_entry_path(@time_entry.project, options)
125 126 elsif params[:issue_id] && @time_entry.issue
126 127 redirect_to new_issue_time_entry_path(@time_entry.issue, options)
127 128 else
128 129 redirect_to new_time_entry_path(options)
129 130 end
130 131 else
131 132 redirect_back_or_default project_time_entries_path(@time_entry.project)
132 133 end
133 134 }
134 135 format.api { render :action => 'show', :status => :created, :location => time_entry_url(@time_entry) }
135 136 end
136 137 else
137 138 respond_to do |format|
138 139 format.html { render :action => 'new' }
139 140 format.api { render_validation_errors(@time_entry) }
140 141 end
141 142 end
142 143 end
143 144
144 145 def edit
145 146 @time_entry.safe_attributes = params[:time_entry]
146 147 end
147 148
148 149 def update
149 150 @time_entry.safe_attributes = params[:time_entry]
150 151
151 152 call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
152 153
153 154 if @time_entry.save
154 155 respond_to do |format|
155 156 format.html {
156 157 flash[:notice] = l(:notice_successful_update)
157 158 redirect_back_or_default project_time_entries_path(@time_entry.project)
158 159 }
159 160 format.api { render_api_ok }
160 161 end
161 162 else
162 163 respond_to do |format|
163 164 format.html { render :action => 'edit' }
164 165 format.api { render_validation_errors(@time_entry) }
165 166 end
166 167 end
167 168 end
168 169
169 170 def bulk_edit
170 171 @available_activities = TimeEntryActivity.shared.active
171 172 @custom_fields = TimeEntry.first.available_custom_fields.select {|field| field.format.bulk_edit_supported}
172 173 end
173 174
174 175 def bulk_update
175 176 attributes = parse_params_for_bulk_update(params[:time_entry])
176 177
177 178 unsaved_time_entry_ids = []
178 179 @time_entries.each do |time_entry|
179 180 time_entry.reload
180 181 time_entry.safe_attributes = attributes
181 182 call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry })
182 183 unless time_entry.save
183 184 logger.info "time entry could not be updated: #{time_entry.errors.full_messages}" if logger && logger.info?
184 185 # Keep unsaved time_entry ids to display them in flash error
185 186 unsaved_time_entry_ids << time_entry.id
186 187 end
187 188 end
188 189 set_flash_from_bulk_time_entry_save(@time_entries, unsaved_time_entry_ids)
189 190 redirect_back_or_default project_time_entries_path(@projects.first)
190 191 end
191 192
192 193 def destroy
193 194 destroyed = TimeEntry.transaction do
194 195 @time_entries.each do |t|
195 196 unless t.destroy && t.destroyed?
196 197 raise ActiveRecord::Rollback
197 198 end
198 199 end
199 200 end
200 201
201 202 respond_to do |format|
202 203 format.html {
203 204 if destroyed
204 205 flash[:notice] = l(:notice_successful_delete)
205 206 else
206 207 flash[:error] = l(:notice_unable_delete_time_entry)
207 208 end
208 209 redirect_back_or_default project_time_entries_path(@projects.first)
209 210 }
210 211 format.api {
211 212 if destroyed
212 213 render_api_ok
213 214 else
214 215 render_validation_errors(@time_entries)
215 216 end
216 217 }
217 218 end
218 219 end
219 220
220 221 private
221 222 def find_time_entry
222 223 @time_entry = TimeEntry.find(params[:id])
223 224 unless @time_entry.editable_by?(User.current)
224 225 render_403
225 226 return false
226 227 end
227 228 @project = @time_entry.project
228 229 rescue ActiveRecord::RecordNotFound
229 230 render_404
230 231 end
231 232
232 233 def find_time_entries
233 234 @time_entries = TimeEntry.where(:id => params[:id] || params[:ids]).preload(:project, :user).to_a
234 235 raise ActiveRecord::RecordNotFound if @time_entries.empty?
235 236 raise Unauthorized unless @time_entries.all? {|t| t.editable_by?(User.current)}
236 237 @projects = @time_entries.collect(&:project).compact.uniq
237 238 @project = @projects.first if @projects.size == 1
238 239 rescue ActiveRecord::RecordNotFound
239 240 render_404
240 241 end
241 242
242 243 def set_flash_from_bulk_time_entry_save(time_entries, unsaved_time_entry_ids)
243 244 if unsaved_time_entry_ids.empty?
244 245 flash[:notice] = l(:notice_successful_update) unless time_entries.empty?
245 246 else
246 247 flash[:error] = l(:notice_failed_to_save_time_entries,
247 248 :count => unsaved_time_entry_ids.size,
248 249 :total => time_entries.size,
249 250 :ids => '#' + unsaved_time_entry_ids.join(', #'))
250 251 end
251 252 end
252 253
253 254 def find_optional_issue
254 255 if params[:issue_id].present?
255 256 @issue = Issue.find(params[:issue_id])
256 257 @project = @issue.project
257 258 else
258 259 find_optional_project
259 260 end
260 261 end
261 262
262 263 def find_optional_project
263 264 if params[:project_id].present?
264 265 @project = Project.find(params[:project_id])
265 266 end
266 267 rescue ActiveRecord::RecordNotFound
267 268 render_404
268 269 end
269 270
270 271 # Returns the TimeEntry scope for index and report actions
271 272 def time_entry_scope(options={})
272 273 @query.results_scope(options)
273 274 end
274 275
275 276 def retrieve_time_entry_query
276 277 retrieve_query(TimeEntryQuery, false)
277 278 end
278 279 end
General Comments 0
You need to be logged in to leave comments. Login now