##// END OF EJS Templates
git-svn-id: http://redmine.rubyforge.org/svn/trunk@51 e93f8b46-1217-0410-a6f0-8f06a7374b81
Jean-Philippe Lang -
r49:c83e79487171
parent child
Show More
@@ -1,65 +1,68
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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 DocumentsController < ApplicationController
19 19 layout 'base'
20 20 before_filter :find_project, :authorize
21 21
22 22 def show
23 23 @attachments = @document.attachments.find(:all, :order => "created_on DESC")
24 24 end
25 25
26 26 def edit
27 27 @categories = Enumeration::get_values('DCAT')
28 28 if request.post? and @document.update_attributes(params[:document])
29 29 flash[:notice] = l(:notice_successful_update)
30 30 redirect_to :action => 'show', :id => @document
31 31 end
32 32 end
33 33
34 34 def destroy
35 35 @document.destroy
36 36 redirect_to :controller => 'projects', :action => 'list_documents', :id => @project
37 37 end
38 38
39 39 def download
40 40 @attachment = @document.attachments.find(params[:attachment_id])
41 41 @attachment.increment_download
42 42 send_file @attachment.diskfile, :filename => @attachment.filename
43 rescue
44 flash.now[:notice] = l(:notice_file_not_found)
45 render :text => "", :layout => true, :status => 404
43 46 end
44 47
45 48 def add_attachment
46 49 # Save the attachment
47 50 if params[:attachment][:file].size > 0
48 51 @attachment = @document.attachments.build(params[:attachment])
49 52 @attachment.author_id = self.logged_in_user.id if self.logged_in_user
50 53 @attachment.save
51 54 end
52 55 redirect_to :action => 'show', :id => @document
53 56 end
54 57
55 58 def destroy_attachment
56 59 @document.attachments.find(params[:attachment_id]).destroy
57 60 redirect_to :action => 'show', :id => @document
58 61 end
59 62
60 63 private
61 64 def find_project
62 65 @document = Document.find(params[:id])
63 66 @project = @document.project
64 67 end
65 68 end
@@ -1,130 +1,133
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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 IssuesController < ApplicationController
19 19 layout 'base', :except => :export_pdf
20 20 before_filter :find_project, :authorize
21 21
22 22 helper :custom_fields
23 23 include CustomFieldsHelper
24 24 helper :ifpdf
25 25 include IfpdfHelper
26 26
27 27 def show
28 28 @status_options = @issue.status.workflows.find(:all, :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
29 29 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
30 30 end
31 31
32 32 def export_pdf
33 33 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
34 34 @options_for_rfpdf ||= {}
35 35 @options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.long_id}.pdf"
36 36 end
37 37
38 38 def edit
39 39 @priorities = Enumeration::get_values('IPRI')
40 40 if request.get?
41 41 @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
42 42 else
43 43 begin
44 44 # Retrieve custom fields and values
45 45 @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
46 46 @issue.custom_values = @custom_values
47 47 @issue.attributes = params[:issue]
48 48 if @issue.save
49 49 flash[:notice] = l(:notice_successful_update)
50 50 redirect_to :action => 'show', :id => @issue
51 51 end
52 52 rescue ActiveRecord::StaleObjectError
53 53 # Optimistic locking exception
54 54 flash[:notice] = l(:notice_locking_conflict)
55 55 end
56 56 end
57 57 end
58 58
59 59 def add_note
60 60 unless params[:history][:notes].empty?
61 61 @history = @issue.histories.build(params[:history])
62 62 @history.author_id = self.logged_in_user.id if self.logged_in_user
63 63 @history.status = @issue.status
64 64 if @history.save
65 65 flash[:notice] = l(:notice_successful_update)
66 66 Mailer.deliver_issue_add_note(@history) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
67 67 redirect_to :action => 'show', :id => @issue
68 68 return
69 69 end
70 70 end
71 71 show
72 72 render :action => 'show'
73 73 end
74 74
75 75 def change_status
76 76 @history = @issue.histories.build(params[:history])
77 77 @status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
78 78 if params[:confirm]
79 79 begin
80 80 @history.author_id = self.logged_in_user.id if self.logged_in_user
81 81 @issue.status = @history.status
82 82 @issue.fixed_version_id = (params[:issue][:fixed_version_id])
83 83 @issue.assigned_to_id = (params[:issue][:assigned_to_id])
84 84 @issue.done_ratio = (params[:issue][:done_ratio])
85 85 @issue.lock_version = (params[:issue][:lock_version])
86 86 if @issue.save
87 87 flash[:notice] = l(:notice_successful_update)
88 88 Mailer.deliver_issue_change_status(@issue) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
89 89 redirect_to :action => 'show', :id => @issue
90 90 end
91 91 rescue ActiveRecord::StaleObjectError
92 92 # Optimistic locking exception
93 93 flash[:notice] = l(:notice_locking_conflict)
94 94 end
95 95 end
96 96 @assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
97 97 end
98 98
99 99 def destroy
100 100 @issue.destroy
101 101 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
102 102 end
103 103
104 104 def add_attachment
105 105 # Save the attachments
106 106 params[:attachments].each { |a|
107 107 @attachment = @issue.attachments.build(:file => a, :author => self.logged_in_user) unless a.size == 0
108 108 @attachment.save
109 109 } if params[:attachments] and params[:attachments].is_a? Array
110 110 redirect_to :action => 'show', :id => @issue
111 111 end
112 112
113 113 def destroy_attachment
114 114 @issue.attachments.find(params[:attachment_id]).destroy
115 115 redirect_to :action => 'show', :id => @issue
116 116 end
117 117
118 118 # Send the file in stream mode
119 119 def download
120 120 @attachment = @issue.attachments.find(params[:attachment_id])
121 121 send_file @attachment.diskfile, :filename => @attachment.filename
122 rescue
123 flash.now[:notice] = l(:notice_file_not_found)
124 render :text => "", :layout => true, :status => 404
122 125 end
123 126
124 127 private
125 128 def find_project
126 129 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
127 130 @project = @issue.project
128 131 @html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
129 132 end
130 133 end
@@ -1,468 +1,468
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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 ProjectsController < ApplicationController
19 19 layout 'base', :except => :export_issues_pdf
20 20 before_filter :find_project, :authorize, :except => [ :index, :list, :add ]
21 21 before_filter :require_admin, :only => [ :add, :destroy ]
22 22
23 23 helper :sort
24 24 include SortHelper
25 25 helper :search_filter
26 26 include SearchFilterHelper
27 27 helper :custom_fields
28 28 include CustomFieldsHelper
29 29 helper :ifpdf
30 30 include IfpdfHelper
31 31
32 32 def index
33 33 list
34 34 render :action => 'list' unless request.xhr?
35 35 end
36 36
37 37 # Lists public projects
38 38 def list
39 39 sort_init 'name', 'asc'
40 40 sort_update
41 41 @project_count = Project.count(["is_public=?", true])
42 42 @project_pages = Paginator.new self, @project_count,
43 43 15,
44 44 @params['page']
45 45 @projects = Project.find :all, :order => sort_clause,
46 46 :conditions => ["is_public=?", true],
47 47 :limit => @project_pages.items_per_page,
48 48 :offset => @project_pages.current.offset
49 49
50 50 render :action => "list", :layout => false if request.xhr?
51 51 end
52 52
53 53 # Add a new project
54 54 def add
55 55 @custom_fields = IssueCustomField.find(:all)
56 56 @root_projects = Project.find(:all, :conditions => "parent_id is null")
57 57 @project = Project.new(params[:project])
58 58 if request.get?
59 59 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
60 60 else
61 61 @project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
62 62 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
63 63 @project.custom_values = @custom_values
64 64 if @project.save
65 65 flash[:notice] = l(:notice_successful_create)
66 66 redirect_to :controller => 'admin', :action => 'projects'
67 67 end
68 68 end
69 69 end
70 70
71 71 # Show @project
72 72 def show
73 73 @custom_values = @project.custom_values.find(:all, :include => :custom_field)
74 74 @members = @project.members.find(:all, :include => [:user, :role])
75 75 @subprojects = @project.children if @project.children_count > 0
76 76 @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "news.created_on DESC")
77 77 @trackers = Tracker.find(:all)
78 78 end
79 79
80 80 def settings
81 81 @root_projects = Project::find(:all, :conditions => ["parent_id is null and id <> ?", @project.id])
82 82 @custom_fields = IssueCustomField::find_all
83 83 @issue_category ||= IssueCategory.new
84 84 @member ||= @project.members.new
85 85 @roles = Role.find_all
86 86 @users = User.find_all - @project.members.find(:all, :include => :user).collect{|m| m.user }
87 87 @custom_values ||= ProjectCustomField.find(:all).collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
88 88 end
89 89
90 90 # Edit @project
91 91 def edit
92 92 if request.post?
93 93 @project.custom_fields = IssueCustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
94 94 if params[:custom_fields]
95 95 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
96 96 @project.custom_values = @custom_values
97 97 end
98 98 if @project.update_attributes(params[:project])
99 99 flash[:notice] = l(:notice_successful_update)
100 100 redirect_to :action => 'settings', :id => @project
101 101 else
102 102 settings
103 103 render :action => 'settings'
104 104 end
105 105 end
106 106 end
107 107
108 108 # Delete @project
109 109 def destroy
110 110 if request.post? and params[:confirm]
111 111 @project.destroy
112 112 redirect_to :controller => 'admin', :action => 'projects'
113 113 end
114 114 end
115 115
116 116 # Add a new issue category to @project
117 117 def add_issue_category
118 118 if request.post?
119 119 @issue_category = @project.issue_categories.build(params[:issue_category])
120 120 if @issue_category.save
121 121 flash[:notice] = l(:notice_successful_create)
122 122 redirect_to :action => 'settings', :id => @project
123 123 else
124 124 settings
125 125 render :action => 'settings'
126 126 end
127 127 end
128 128 end
129 129
130 130 # Add a new version to @project
131 131 def add_version
132 132 @version = @project.versions.build(params[:version])
133 133 if request.post? and @version.save
134 134 flash[:notice] = l(:notice_successful_create)
135 135 redirect_to :action => 'settings', :id => @project
136 136 end
137 137 end
138 138
139 139 # Add a new member to @project
140 140 def add_member
141 141 @member = @project.members.build(params[:member])
142 142 if request.post?
143 143 if @member.save
144 144 flash[:notice] = l(:notice_successful_create)
145 145 redirect_to :action => 'settings', :id => @project
146 146 else
147 147 settings
148 148 render :action => 'settings'
149 149 end
150 150 end
151 151 end
152 152
153 153 # Show members list of @project
154 154 def list_members
155 155 @members = @project.members
156 156 end
157 157
158 158 # Add a new document to @project
159 159 def add_document
160 160 @categories = Enumeration::get_values('DCAT')
161 161 @document = @project.documents.build(params[:document])
162 162 if request.post?
163 163 # Save the attachment
164 164 if params[:attachment][:file].size > 0
165 165 @attachment = @document.attachments.build(params[:attachment])
166 166 @attachment.author_id = self.logged_in_user.id if self.logged_in_user
167 167 end
168 168 if @document.save
169 169 flash[:notice] = l(:notice_successful_create)
170 170 redirect_to :action => 'list_documents', :id => @project
171 171 end
172 172 end
173 173 end
174 174
175 175 # Show documents list of @project
176 176 def list_documents
177 177 @documents = @project.documents
178 178 end
179 179
180 180 # Add a new issue to @project
181 181 def add_issue
182 182 @tracker = Tracker.find(params[:tracker_id])
183 183 @priorities = Enumeration::get_values('IPRI')
184 184 @issue = Issue.new(:project => @project, :tracker => @tracker)
185 185 if request.get?
186 186 @issue.start_date = Date.today
187 187 @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) }
188 188 else
189 189 @issue.attributes = params[:issue]
190 190 @issue.author_id = self.logged_in_user.id if self.logged_in_user
191 191 # Multiple file upload
192 192 params[:attachments].each { |a|
193 193 @attachment = @issue.attachments.build(:file => a, :author => self.logged_in_user) unless a.size == 0
194 194 } if params[:attachments] and params[:attachments].is_a? Array
195 195 @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
196 196 @issue.custom_values = @custom_values
197 197 if @issue.save
198 198 flash[:notice] = l(:notice_successful_create)
199 199 Mailer.deliver_issue_add(@issue) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
200 200 redirect_to :action => 'list_issues', :id => @project
201 201 end
202 202 end
203 203 end
204 204
205 205 # Show filtered/sorted issues list of @project
206 206 def list_issues
207 207 sort_init 'issues.id', 'desc'
208 208 sort_update
209 209
210 210 search_filter_init_list_issues
211 211 search_filter_update if params[:set_filter]
212 212
213 213 @results_per_page_options = [ 15, 25, 50, 100 ]
214 214 if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
215 215 @results_per_page = params[:per_page].to_i
216 216 session[:results_per_page] = @results_per_page
217 217 else
218 218 @results_per_page = session[:results_per_page] || 25
219 219 end
220 220
221 221 @issue_count = Issue.count(:include => [:status, :project], :conditions => search_filter_clause)
222 222 @issue_pages = Paginator.new self, @issue_count, @results_per_page, @params['page']
223 223 @issues = Issue.find :all, :order => sort_clause,
224 224 :include => [ :author, :status, :tracker, :project ],
225 225 :conditions => search_filter_clause,
226 226 :limit => @issue_pages.items_per_page,
227 227 :offset => @issue_pages.current.offset
228 228
229 229 render :layout => false if request.xhr?
230 230 end
231 231
232 232 # Export filtered/sorted issues list to CSV
233 233 def export_issues_csv
234 234 sort_init 'issues.id', 'desc'
235 235 sort_update
236 236
237 237 search_filter_init_list_issues
238 238
239 239 @issues = Issue.find :all, :order => sort_clause,
240 240 :include => [ :author, :status, :tracker, :project, :custom_values ],
241 241 :conditions => search_filter_clause
242 242
243 243 ic = Iconv.new('ISO-8859-1', 'UTF-8')
244 244 export = StringIO.new
245 245 CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
246 246 # csv header fields
247 247 headers = [ "#", l(:field_status), l(:field_tracker), l(:field_subject), l(:field_author), l(:field_created_on), l(:field_updated_on) ]
248 248 for custom_field in @project.all_custom_fields
249 249 headers << custom_field.name
250 250 end
251 251 csv << headers.collect {|c| ic.iconv(c) }
252 252 # csv lines
253 253 @issues.each do |issue|
254 254 fields = [issue.id, issue.status.name, issue.tracker.name, issue.subject, issue.author.display_name, l_datetime(issue.created_on), l_datetime(issue.updated_on)]
255 255 for custom_field in @project.all_custom_fields
256 256 fields << (show_value issue.custom_value_for(custom_field))
257 257 end
258 258 csv << fields.collect {|c| ic.iconv(c.to_s) }
259 259 end
260 260 end
261 261 export.rewind
262 262 send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
263 263 end
264 264
265 265 # Export filtered/sorted issues to PDF
266 266 def export_issues_pdf
267 267 sort_init 'issues.id', 'desc'
268 268 sort_update
269 269
270 270 search_filter_init_list_issues
271 271
272 272 @issues = Issue.find :all, :order => sort_clause,
273 273 :include => [ :author, :status, :tracker, :project, :custom_values ],
274 274 :conditions => search_filter_clause
275 275
276 276 @options_for_rfpdf ||= {}
277 277 @options_for_rfpdf[:file_name] = "export.pdf"
278 278 end
279 279
280 280 def move_issues
281 281 @issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids]
282 282 redirect_to :action => 'list_issues', :id => @project and return unless @issues
283 283 @projects = []
284 284 # find projects to which the user is allowed to move the issue
285 285 @logged_in_user.memberships.each {|m| @projects << m.project if Permission.allowed_to_role("projects/move_issues", m.role_id)}
286 286 # issue can be moved to any tracker
287 287 @trackers = Tracker.find(:all)
288 288 if request.post? and params[:new_project_id] and params[:new_tracker_id]
289 289 new_project = Project.find(params[:new_project_id])
290 290 new_tracker = Tracker.find(params[:new_tracker_id])
291 291 @issues.each { |i|
292 292 # category is project dependent
293 293 i.category = nil unless i.project_id == new_project.id
294 294 # move the issue
295 295 i.project = new_project
296 296 i.tracker = new_tracker
297 297 i.save
298 298 }
299 299 flash[:notice] = l(:notice_successful_update)
300 300 redirect_to :action => 'list_issues', :id => @project
301 301 end
302 302 end
303 303
304 304 # Add a news to @project
305 305 def add_news
306 306 @news = News.new(:project => @project)
307 307 if request.post?
308 308 @news.attributes = params[:news]
309 309 @news.author_id = self.logged_in_user.id if self.logged_in_user
310 310 if @news.save
311 311 flash[:notice] = l(:notice_successful_create)
312 312 redirect_to :action => 'list_news', :id => @project
313 313 end
314 314 end
315 315 end
316 316
317 317 # Show news list of @project
318 318 def list_news
319 319 @news_pages, @news = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "news.created_on DESC"
320 320 render :action => "list_news", :layout => false if request.xhr?
321 321 end
322 322
323 323 def add_file
324 324 if request.post?
325 325 # Save the attachment
326 326 if params[:attachment][:file].size > 0
327 327 @attachment = @project.versions.find(params[:version_id]).attachments.build(params[:attachment])
328 328 @attachment.author_id = self.logged_in_user.id if self.logged_in_user
329 329 if @attachment.save
330 330 flash[:notice] = l(:notice_successful_create)
331 331 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
332 332 end
333 333 end
334 334 end
335 335 @versions = @project.versions
336 336 end
337 337
338 338 def list_files
339 339 @versions = @project.versions
340 340 end
341 341
342 342 # Show changelog for @project
343 343 def changelog
344 344 @trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true])
345 345 if request.get?
346 346 @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
347 347 else
348 348 @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
349 349 end
350 350 @selected_tracker_ids ||= []
351 351 @fixed_issues = @project.issues.find(:all,
352 352 :include => [ :fixed_version, :status, :tracker ],
353 353 :conditions => [ "issue_statuses.is_closed=? and issues.tracker_id in (#{@selected_tracker_ids.join(',')}) and issues.fixed_version_id is not null", true],
354 354 :order => "versions.effective_date DESC, issues.id DESC"
355 355 ) unless @selected_tracker_ids.empty?
356 356 @fixed_issues ||= []
357 357 end
358 358
359 359 def activity
360 360 if params[:year] and params[:year].to_i > 1900
361 361 @year = params[:year].to_i
362 362 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
363 363 @month = params[:month].to_i
364 364 end
365 365 end
366 366 @year ||= Date.today.year
367 367 @month ||= Date.today.month
368 368
369 369 @date_from = Date.civil(@year, @month, 1)
370 370 @date_to = (@date_from >> 1)-1
371 371
372 372 @events_by_day = {}
373 373
374 374 unless params[:show_issues] == "0"
375 375 @project.issues.find(:all, :include => [:author, :status], :conditions => ["issues.created_on>=? and issues.created_on<=?", @date_from, @date_to] ).each { |i|
376 376 @events_by_day[i.created_on.to_date] ||= []
377 377 @events_by_day[i.created_on.to_date] << i
378 378 }
379 379 @show_issues = 1
380 380 end
381 381
382 382 unless params[:show_news] == "0"
383 383 @project.news.find(:all, :conditions => ["news.created_on>=? and news.created_on<=?", @date_from, @date_to] ).each { |i|
384 384 @events_by_day[i.created_on.to_date] ||= []
385 385 @events_by_day[i.created_on.to_date] << i
386 386 }
387 387 @show_news = 1
388 388 end
389 389
390 390 unless params[:show_files] == "0"
391 391 Attachment.find(:all, :joins => "LEFT JOIN versions ON versions.id = attachments.container_id", :conditions => ["attachments.container_type='Version' and versions.project_id=? and attachments.created_on>=? and attachments.created_on<=?", @project.id, @date_from, @date_to] ).each { |i|
392 392 @events_by_day[i.created_on.to_date] ||= []
393 393 @events_by_day[i.created_on.to_date] << i
394 394 }
395 395 @show_files = 1
396 396 end
397 397
398 unless params[:show_documentss] == "0"
398 unless params[:show_documents] == "0"
399 399 Attachment.find(:all, :joins => "LEFT JOIN documents ON documents.id = attachments.container_id", :conditions => ["attachments.container_type='Document' and documents.project_id=? and attachments.created_on>=? and attachments.created_on<=?", @project.id, @date_from, @date_to] ).each { |i|
400 400 @events_by_day[i.created_on.to_date] ||= []
401 401 @events_by_day[i.created_on.to_date] << i
402 402 }
403 403 @show_documents = 1
404 404 end
405 405
406 406 end
407 407
408 408 def calendar
409 409 if params[:year] and params[:year].to_i > 1900
410 410 @year = params[:year].to_i
411 411 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
412 412 @month = params[:month].to_i
413 413 end
414 414 end
415 415 @year ||= Date.today.year
416 416 @month ||= Date.today.month
417 417
418 418 @date_from = Date.civil(@year, @month, 1)
419 419 @date_to = (@date_from >> 1)-1
420 420 # start on monday
421 421 @date_from = @date_from - (@date_from.cwday-1)
422 422 # finish on sunday
423 423 @date_to = @date_to + (7-@date_to.cwday)
424 424
425 425 @issues = @project.issues.find(:all, :include => :tracker, :conditions => ["((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?))", @date_from, @date_to, @date_from, @date_to])
426 426 render :layout => false if request.xhr?
427 427 end
428 428
429 429 def gantt
430 430 if params[:year] and params[:year].to_i >0
431 431 @year_from = params[:year].to_i
432 432 if params[:month] and params[:month].to_i >=1 and params[:month].to_i <= 12
433 433 @month_from = params[:month].to_i
434 434 else
435 435 @month_from = 1
436 436 end
437 437 else
438 438 @month_from ||= (Date.today << 1).month
439 439 @year_from ||= (Date.today << 1).year
440 440 end
441 441
442 442 @zoom = (params[:zoom].to_i > 0 and params[:zoom].to_i < 5) ? params[:zoom].to_i : 2
443 443 @months = (params[:months].to_i > 0 and params[:months].to_i < 25) ? params[:months].to_i : 6
444 444
445 445 @date_from = Date.civil(@year_from, @month_from, 1)
446 446 @date_to = (@date_from >> @months) - 1
447 447 @issues = @project.issues.find(:all, :order => "start_date, due_date", :conditions => ["(((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?) or (start_date<? and due_date>?)) and start_date is not null and due_date is not null)", @date_from, @date_to, @date_from, @date_to, @date_from, @date_to])
448 448
449 449 if params[:output]=='pdf'
450 450 @options_for_rfpdf ||= {}
451 451 @options_for_rfpdf[:file_name] = "gantt.pdf"
452 452 render :template => "projects/gantt.rfpdf", :layout => false
453 453 else
454 454 render :template => "projects/gantt.rhtml"
455 455 end
456 456 end
457 457
458 458 private
459 459 # Find project of id params[:id]
460 460 # if not found, redirect to project list
461 461 # Used as a before_filter
462 462 def find_project
463 463 @project = Project.find(params[:id])
464 464 @html_title = @project.name
465 465 rescue
466 466 redirect_to :action => 'list'
467 467 end
468 468 end
@@ -1,128 +1,164
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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 ReportsController < ApplicationController
19 19 layout 'base'
20 20 before_filter :find_project, :authorize
21 21
22 22 def issue_report
23 23 @statuses = IssueStatus.find_all
24 24
25 25 case params[:detail]
26 26 when "tracker"
27 27 @field = "tracker_id"
28 28 @rows = Tracker.find_all
29 29 @data = issues_by_tracker
30 30 @report_title = l(:field_tracker)
31 31 render :template => "reports/issue_report_details"
32 32 when "priority"
33 33 @field = "priority_id"
34 34 @rows = Enumeration::get_values('IPRI')
35 35 @data = issues_by_priority
36 36 @report_title = l(:field_priority)
37 37 render :template => "reports/issue_report_details"
38 38 when "category"
39 39 @field = "category_id"
40 40 @rows = @project.issue_categories
41 41 @data = issues_by_category
42 42 @report_title = l(:field_category)
43 43 render :template => "reports/issue_report_details"
44 44 when "author"
45 45 @field = "author_id"
46 46 @rows = @project.members.collect { |m| m.user }
47 47 @data = issues_by_author
48 48 @report_title = l(:field_author)
49 49 render :template => "reports/issue_report_details"
50 50 else
51 51 @trackers = Tracker.find(:all)
52 52 @priorities = Enumeration::get_values('IPRI')
53 53 @categories = @project.issue_categories
54 54 @authors = @project.members.collect { |m| m.user }
55 55 issues_by_tracker
56 56 issues_by_priority
57 57 issues_by_category
58 58 issues_by_author
59 59 render :template => "reports/issue_report"
60 60 end
61 61 end
62 62
63 def delays
64 @trackers = Tracker.find(:all)
65 if request.get?
66 @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
67 else
68 @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
69 end
70 @selected_tracker_ids ||= []
71 @raw =
72 ActiveRecord::Base.connection.select_all("SELECT datediff( a.created_on, b.created_on ) as delay, count(a.id) as total
73 FROM issue_histories a, issue_histories b, issues i
74 WHERE a.status_id =5
75 AND a.issue_id = b.issue_id
76 AND a.issue_id = i.id
77 AND i.tracker_id in (#{@selected_tracker_ids.join(',')})
78 AND b.id = (
79 SELECT min( c.id )
80 FROM issue_histories c
81 WHERE b.issue_id = c.issue_id )
82 GROUP BY delay") unless @selected_tracker_ids.empty?
83 @raw ||=[]
84
85 @x_from = 0
86 @x_to = 0
87 @y_from = 0
88 @y_to = 0
89 @sum_total = 0
90 @sum_delay = 0
91 @raw.each do |r|
92 @x_to = [r['delay'].to_i, @x_to].max
93 @y_to = [r['total'].to_i, @y_to].max
94 @sum_total = @sum_total + r['total'].to_i
95 @sum_delay = @sum_delay + r['total'].to_i * r['delay'].to_i
96 end
97 end
98
63 99 private
64 100 # Find project of id params[:id]
65 101 def find_project
66 102 @project = Project.find(params[:id])
67 103 end
68 104
69 105 def issues_by_tracker
70 106 @issues_by_tracker ||=
71 107 ActiveRecord::Base.connection.select_all("select s.id as status_id,
72 108 s.is_closed as closed,
73 109 t.id as tracker_id,
74 110 count(i.id) as total
75 111 from
76 112 issues i, issue_statuses s, trackers t
77 113 where
78 114 i.status_id=s.id
79 115 and i.tracker_id=t.id
80 116 and i.project_id=#{@project.id}
81 117 group by s.id, s.is_closed, t.id")
82 118 end
83 119
84 120 def issues_by_priority
85 121 @issues_by_priority ||=
86 122 ActiveRecord::Base.connection.select_all("select s.id as status_id,
87 123 s.is_closed as closed,
88 124 p.id as priority_id,
89 125 count(i.id) as total
90 126 from
91 127 issues i, issue_statuses s, enumerations p
92 128 where
93 129 i.status_id=s.id
94 130 and i.priority_id=p.id
95 131 and i.project_id=#{@project.id}
96 132 group by s.id, s.is_closed, p.id")
97 133 end
98 134
99 135 def issues_by_category
100 136 @issues_by_category ||=
101 137 ActiveRecord::Base.connection.select_all("select s.id as status_id,
102 138 s.is_closed as closed,
103 139 c.id as category_id,
104 140 count(i.id) as total
105 141 from
106 142 issues i, issue_statuses s, issue_categories c
107 143 where
108 144 i.status_id=s.id
109 145 and i.category_id=c.id
110 146 and i.project_id=#{@project.id}
111 147 group by s.id, s.is_closed, c.id")
112 148 end
113 149
114 150 def issues_by_author
115 151 @issues_by_author ||=
116 152 ActiveRecord::Base.connection.select_all("select s.id as status_id,
117 153 s.is_closed as closed,
118 154 a.id as author_id,
119 155 count(i.id) as total
120 156 from
121 157 issues i, issue_statuses s, users a
122 158 where
123 159 i.status_id=s.id
124 160 and i.author_id=a.id
125 161 and i.project_id=#{@project.id}
126 162 group by s.id, s.is_closed, a.id")
127 163 end
128 164 end
@@ -1,57 +1,57
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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 VersionsController < ApplicationController
19 19 layout 'base'
20 20 before_filter :find_project, :authorize
21 21
22 22 def edit
23 23 if request.post? and @version.update_attributes(params[:version])
24 24 flash[:notice] = l(:notice_successful_update)
25 25 redirect_to :controller => 'projects', :action => 'settings', :id => @project
26 26 end
27 27 end
28 28
29 29 def destroy
30 30 @version.destroy
31 31 redirect_to :controller => 'projects', :action => 'settings', :id => @project
32 32 rescue
33 33 flash[:notice] = "Unable to delete version"
34 34 redirect_to :controller => 'projects', :action => 'settings', :id => @project
35 35 end
36 36
37 37 def download
38 38 @attachment = @version.attachments.find(params[:attachment_id])
39 39 @attachment.increment_download
40 40 send_file @attachment.diskfile, :filename => @attachment.filename
41 41 rescue
42 flash[:notice] = l(:notice_file_not_found)
43 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
42 flash.now[:notice] = l(:notice_file_not_found)
43 render :text => "", :layout => true, :status => 404
44 44 end
45 45
46 46 def destroy_file
47 47 @version.attachments.find(params[:attachment_id]).destroy
48 48 flash[:notice] = l(:notice_successful_delete)
49 49 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
50 50 end
51 51
52 52 private
53 53 def find_project
54 54 @version = Version.find(params[:id])
55 55 @project = @version.project
56 56 end
57 57 end
@@ -1,43 +1,48
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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 require 'iconv'
19 19
20 20 module IfpdfHelper
21 21
22 22 class IFPDF < FPDF
23 23
24 attr_accessor :footer_date
25
24 26 def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
25 27 @ic ||= Iconv.new('ISO-8859-1', 'UTF-8')
26 28 super w,h,@ic.iconv(txt),border,ln,align,fill,link
27 29 end
28 30
29 31 def MultiCell(w,h,txt,border=0,align='J',fill=0)
30 32 @ic ||= Iconv.new('ISO-8859-1', 'UTF-8')
31 33 super w,h,txt,border,align,fill
32 34 end
33 35
34 36 def Footer
37 SetFont('Helvetica', 'I', 8)
38 SetY(-15)
39 SetX(15)
40 Cell(0, 5, @footer_date, 0, 0, 'L')
35 41 SetY(-15)
36 42 SetX(-30)
37 SetFont('Helvetica', 'I', 8)
38 43 Cell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
39 44 end
40 45
41 46 end
42 47
43 48 end
@@ -1,8 +1,9
1 1 <% pdf=IfpdfHelper::IFPDF.new
2 2 pdf.AliasNbPages
3 pdf.footer_date = format_date(Date.today)
3 4 pdf.AddPage
4 5
5 6 render :partial => 'issues/pdf', :locals => { :pdf => pdf, :issue => @issue }
6 7 %>
7 8
8 9 <%= pdf.Output %> No newline at end of file
@@ -1,41 +1,41
1 1 <h2><%=l(:label_activity)%></h2>
2 2
3 3 <div>
4 4 <div class="rightbox">
5 5 <%= start_form_tag %>
6 6 <p><%= select_month(@month, :prefix => "month", :discard_type => true) %>
7 7 <%= select_year(@year, :prefix => "year", :discard_type => true) %></p>
8 8 <%= check_box_tag 'show_issues', 1, @show_issues %><%= hidden_field_tag 'show_issues', 0 %> <%=l(:label_issue_plural)%><br />
9 9 <%= check_box_tag 'show_news', 1, @show_news %><%= hidden_field_tag 'show_news', 0 %> <%=l(:label_news_plural)%><br />
10 10 <%= check_box_tag 'show_files', 1, @show_files %><%= hidden_field_tag 'show_files', 0 %> <%=l(:label_attachment_plural)%><br />
11 11 <%= check_box_tag 'show_documents', 1, @show_documents %><%= hidden_field_tag 'show_documents', 0 %> <%=l(:label_document_plural)%><br />
12 12 <p><center><%= submit_tag l(:button_apply), :class => 'button-small' %></center></p>
13 13 <%= end_form_tag %>
14 14 </div>
15 15 <% @events_by_day.keys.sort {|x,y| y <=> x }.each do |day| %>
16 <h3><%= format_date(day) %></h3>
16 <h3><%= day_name(day.cwday) %> <%= format_date(day) %></h3>
17 17 <ul>
18 18 <% @events_by_day[day].sort {|x,y| y.created_on <=> x.created_on }.each do |e| %>
19 19 <li><p>
20 20 <% if e.is_a? Issue %>
21 21 <%= e.created_on.strftime("%H:%M") %> <%= e.tracker.name %> <%= link_to e.long_id, :controller => 'issues', :action => 'show', :id => e %> (<%= e.status.name %>): <%= e.subject %><br />
22 22 <i><%= e.author.name %></i>
23 23 <% elsif e.is_a? News %>
24 24 <%= e.created_on.strftime("%H:%M") %> <%=l(:label_news)%>: <%= link_to e.title, :controller => 'news', :action => 'show', :id => e %><br />
25 25 <% unless e.summary.empty? %><%= e.summary %><br /><% end %>
26 26 <i><%= e.author.name %></i>
27 27 <% elsif (e.is_a? Attachment) and (e.container.is_a? Version) %>
28 28 <%= e.created_on.strftime("%H:%M") %> <%=l(:label_attachment)%> (Version <%= e.container.name %>): <%= link_to e.filename, :controller => 'projects', :action => 'list_files', :id => @project %><br />
29 29 <i><%= e.author.name %></i>
30 30 <% elsif (e.is_a? Attachment) and (e.container.is_a? Document) %>
31 31 <%= e.created_on.strftime("%H:%M") %> <%=l(:label_document)%>: <%= link_to e.container.title, :controller => 'documents', :action => 'show', :id => e %><br />
32 32 <i><%= e.author.name %></i>
33 33 <% end %>
34 34 </p></li>
35 35
36 36 <% end %>
37 37 </ul>
38 38 <% end %>
39 39 <% if @events_by_day.empty? %><p><i><%= l(:label_no_data) %></i></p><% end %>
40 40 <br />
41 41 </div> No newline at end of file
@@ -1,27 +1,28
1 1 <h2><%=l(:label_change_log)%></h2>
2 2
3 3 <div>
4 4
5 5 <div class="rightbox" style="width:140px;">
6 6 <%= start_form_tag %>
7 7 <strong><%=l(:label_tracker_plural)%></strong><br />
8 8 <% @trackers.each do |tracker| %>
9 9 <%= check_box_tag "tracker_ids[]", tracker.id, (@selected_tracker_ids.include? tracker.id.to_s) %>
10 10 <%= tracker.name %><br />
11 11 <% end %>
12 12 <p><center><%= submit_tag l(:button_apply), :class => 'button-small' %></center></p>
13 13 <%= end_form_tag %>
14 14 </div>
15 15
16 16 <% ver_id = nil
17 17 @fixed_issues.each do |issue| %>
18 18 <% unless ver_id == issue.fixed_version_id %>
19 19 <% if ver_id %></ul><% end %>
20 <p><strong><%= issue.fixed_version.name %></strong> - <%= format_date(issue.fixed_version.effective_date) %><br />
20 <h3><%= l(:label_version) %>: <%= issue.fixed_version.name %></h3>
21 <p><%= format_date(issue.fixed_version.effective_date) %><br />
21 22 <%=h issue.fixed_version.description %></p>
22 23 <ul>
23 24 <% ver_id = issue.fixed_version_id
24 25 end %>
25 26 <li><%= link_to issue.long_id, :controller => 'issues', :action => 'show', :id => issue %> [<%= issue.tracker.name %>]: <%= issue.subject %></li>
26 27 <% end %>
27 28 </div> No newline at end of file
@@ -1,10 +1,11
1 1 <% pdf=IfpdfHelper::IFPDF.new
2 2 pdf.AliasNbPages
3 pdf.footer_date = format_date(Date.today)
3 4 pdf.AddPage
4 5 @issues.each {|i|
5 6 render :partial => 'issues/pdf', :locals => { :pdf => pdf, :issue => i }
6 7 pdf.AddPage
7 8 }
8 9 %>
9 10
10 11 <%= pdf.Output %> No newline at end of file
@@ -1,161 +1,168
1 1 <%
2 2 pdf=IfpdfHelper::IFPDF.new
3 3 pdf.AliasNbPages
4 pdf.footer_date = format_date(Date.today)
4 5 pdf.AddPage("L")
6 pdf.SetFont('Arial','B',12)
7 pdf.SetX(15)
8 pdf.Cell(70, 20, @project.name)
9 pdf.Ln
5 10 pdf.SetFont('Arial','B',9)
6 11
7 12 subject_width = 70
8 13 header_heigth = 5
9 14
10 15 headers_heigth = header_heigth
11 16 show_weeks = false
12 17 show_days = false
13 18
14 19 if @months < 7
15 20 show_weeks = true
16 21 headers_heigth = 2*header_heigth
17 22 if @months < 3
18 23 show_days = true
19 24 headers_heigth = 3*header_heigth
20 25 end
21 26 end
22 27
23 28 g_width = 210
24 29 zoom = (g_width) / (@date_to - @date_from + 1)
25 30 g_height = 120
26 31 t_height = g_height + headers_heigth
27 32
33 y_start = pdf.GetY
34
28 35
29 36 #
30 37 # Months headers
31 38 #
32 39 month_f = @date_from
33 40 left = subject_width
34 41 height = header_heigth
35 42 @months.times do
36 43 width = ((month_f >> 1) - month_f) * zoom
37 pdf.SetY(20)
44 pdf.SetY(y_start)
38 45 pdf.SetX(left)
39 46 pdf.Cell(width, height, "#{month_f.year}-#{month_f.month}", "LTR", 0, "C")
40 47 left = left + width
41 48 month_f = month_f >> 1
42 49 end
43 50
44 51 #
45 52 # Weeks headers
46 53 #
47 54 if show_weeks
48 55 left = subject_width
49 56 height = header_heigth
50 57 if @date_from.cwday == 1
51 58 # @date_from is monday
52 59 week_f = @date_from
53 60 else
54 61 # find next monday after @date_from
55 62 week_f = @date_from + (7 - @date_from.cwday + 1)
56 63 width = (7 - @date_from.cwday + 1) * zoom-1
57 pdf.SetY(25)
64 pdf.SetY(y_start + header_heigth)
58 65 pdf.SetX(left)
59 66 pdf.Cell(width + 1, height, "", "LTR")
60 67 left = left + width+1
61 68 end
62 69 while week_f < @date_to
63 70 width = (week_f + 6 <= @date_to) ? 7 * zoom : (@date_to - week_f + 1) * zoom
64 pdf.SetY(25)
71 pdf.SetY(y_start + header_heigth)
65 72 pdf.SetX(left)
66 73 pdf.Cell(width, height, week_f.cweek.to_s, "LTR", 0, "C")
67 74 left = left + width
68 75 week_f = week_f+7
69 76 end
70 77 end
71 78
72 79 #
73 80 # Days headers
74 81 #
75 82 if show_days
76 83 left = subject_width
77 84 height = header_heigth
78 85 wday = @date_from.cwday
79 86 pdf.SetFont('Arial','B',7)
80 87 (@date_to - @date_from + 1).to_i.times do
81 88 width = zoom
82 pdf.SetY(30)
89 pdf.SetY(y_start + 2 * header_heigth)
83 90 pdf.SetX(left)
84 91 pdf.Cell(width, height, day_name(wday)[0,1], "LTR", 0, "C")
85 92 left = left + width
86 93 wday = wday + 1
87 94 wday = 1 if wday > 7
88 95 end
89 96 end
90 97
91 pdf.SetY(20)
98 pdf.SetY(y_start)
92 99 pdf.SetX(15)
93 100 pdf.Cell(subject_width+g_width-15, headers_heigth, "", 1)
94 101
95 102
96 103 #
97 104 # Tasks
98 105 #
99 top = headers_heigth + 20
106 top = headers_heigth + y_start
100 107 pdf.SetFont('Arial','B',7)
101 108 @issues.each do |i|
102 109 pdf.SetY(top)
103 110 pdf.SetX(15)
104 111 pdf.Cell(subject_width-15, 5, i.id.to_s + " " + i.subject.sub(/^(.{30}[^\s]*\s).*$/, '\1 (...)'), "LR")
105 112
106 113 pdf.SetY(top)
107 114 pdf.SetX(subject_width)
108 115 pdf.Cell(g_width, 5, "", "LR")
109 116
110 117 i_start_date = (i.start_date >= @date_from ? i.start_date : @date_from )
111 118 i_end_date = (i.due_date <= @date_to ? i.due_date : @date_to )
112 119
113 120 i_done_date = i.start_date + ((i.due_date - i.start_date)*i.done_ratio/100).floor
114 121 i_done_date = (i_done_date <= @date_from ? @date_from : i_done_date )
115 122 i_done_date = (i_done_date >= @date_to ? @date_to : i_done_date )
116 123
117 124 i_late_date = [i_end_date, Date.today].min if i_start_date < Date.today
118 125
119 126 i_left = ((i_start_date - @date_from)*zoom)
120 127 i_width = ((i_end_date - i_start_date + 1)*zoom)
121 128 d_width = ((i_done_date - i_start_date)*zoom)
122 129 l_width = ((i_late_date - i_start_date+1)*zoom) if i_late_date
123 130 l_width ||= 0
124 131
125 132 pdf.SetY(top+1.5)
126 133 pdf.SetX(subject_width + i_left)
127 134 pdf.SetFillColor(200,200,200)
128 135 pdf.Cell(i_width, 2, "", 0, 0, "", 1)
129 136
130 137 if l_width > 0
131 138 pdf.SetY(top+1.5)
132 139 pdf.SetX(subject_width + i_left)
133 140 pdf.SetFillColor(255,100,100)
134 141 pdf.Cell(l_width, 2, "", 0, 0, "", 1)
135 142 end
136 143 if d_width > 0
137 144 pdf.SetY(top+1.5)
138 145 pdf.SetX(subject_width + i_left)
139 146 pdf.SetFillColor(100,100,255)
140 147 pdf.Cell(d_width, 2, "", 0, 0, "", 1)
141 148 end
142 149
143 150 pdf.SetY(top+1.5)
144 151 pdf.SetX(subject_width + i_left + i_width)
145 152 pdf.Cell(30, 2, "#{i.status.name} #{i.done_ratio}%")
146 153
147 154 top = top + 5
148 155 pdf.SetDrawColor(200, 200, 200)
149 156 pdf.Line(15, top, subject_width+g_width, top)
150 157 if pdf.GetY() > 180
151 158 pdf.AddPage("L")
152 159 top = 20
153 160 pdf.Line(15, top, subject_width+g_width, top)
154 161 end
155 162 pdf.SetDrawColor(0, 0, 0)
156 163 end
157 164
158 165 pdf.Line(15, top, subject_width+g_width, top)
159 166
160 167 %>
161 168 <%= pdf.Output %> No newline at end of file
@@ -1,75 +1,75
1 1 <h2><%=l(:label_issue_plural)%></h2>
2 2 <div class="topright">
3 3 <small>
4 4 <%= link_to 'PDF ', :action => 'export_issues_pdf', :id => @project %> |
5 5 <%= link_to 'CSV ', :action => 'export_issues_csv', :id => @project %>
6 6 </small>
7 7 </div>
8 8
9 <form method="post" class="noborder">
9 <%= start_form_tag :action => 'list_issues' %>
10 10 <table cellpadding=2>
11 11 <tr>
12 <td><small><%=l(:field_status)%>:</small><br /><%= search_filter_tag 'status_id', :class => 'select-small' %></td>
13 <td><small><%=l(:field_tracker)%>:</small><br /><%= search_filter_tag 'tracker_id', :class => 'select-small' %></td>
14 <td><small><%=l(:field_priority)%>:</small><br /><%= search_filter_tag 'priority_id', :class => 'select-small' %></td>
15 <td><small><%=l(:field_category)%>:</small><br /><%= search_filter_tag 'category_id', :class => 'select-small' %></td>
16 <td><small><%=l(:field_fixed_version)%>:</small><br /><%= search_filter_tag 'fixed_version_id', :class => 'select-small' %></td>
17 <td><small><%=l(:field_author)%>:</small><br /><%= search_filter_tag 'author_id', :class => 'select-small' %></td>
18 <td><small><%=l(:field_assigned_to)%>:</small><br /><%= search_filter_tag 'assigned_to_id', :class => 'select-small' %></td>
19 <td><small><%=l(:label_subproject_plural)%>:</small><br /><%= search_filter_tag 'subproject_id', :class => 'select-small' %></td>
12 <td valign="bottom"><small><%=l(:field_status)%>:</small><br /><%= search_filter_tag 'status_id', :class => 'select-small' %></td>
13 <td valign="bottom"><small><%=l(:field_tracker)%>:</small><br /><%= search_filter_tag 'tracker_id', :class => 'select-small' %></td>
14 <td valign="bottom"><small><%=l(:field_priority)%>:</small><br /><%= search_filter_tag 'priority_id', :class => 'select-small' %></td>
15 <td valign="bottom"><small><%=l(:field_category)%>:</small><br /><%= search_filter_tag 'category_id', :class => 'select-small' %></td>
16 <td valign="bottom"><small><%=l(:field_fixed_version)%>:</small><br /><%= search_filter_tag 'fixed_version_id', :class => 'select-small' %></td>
17 <td valign="bottom"><small><%=l(:field_author)%>:</small><br /><%= search_filter_tag 'author_id', :class => 'select-small' %></td>
18 <td valign="bottom"><small><%=l(:field_assigned_to)%>:</small><br /><%= search_filter_tag 'assigned_to_id', :class => 'select-small' %></td>
19 <td valign="bottom"><small><%=l(:label_subproject_plural)%>:</small><br /><%= search_filter_tag 'subproject_id', :class => 'select-small' %></td>
20 20 <td valign="bottom">
21 21 <%= hidden_field_tag 'set_filter', 1 %>
22 22 <%= submit_tag l(:button_apply), :class => 'button-small' %>
23 23 </td>
24 24 <td valign="bottom">
25 25 <%= link_to l(:button_clear), :action => 'list_issues', :id => @project, :set_filter => 1 %>
26 26 </td>
27 27 </tr>
28 28 </table>
29 29 <%= end_form_tag %>
30 30
31 31 &nbsp;
32 32 <table class="listTableContent">
33 33 <tr>
34 34 <td colspan="6" align="left"><small><%= check_all_links 'issues_form' %></small></td>
35 35 <td colspan="2" align="right">
36 36 <small><%= l(:label_per_page) %>:</small>
37 37 <%= start_form_tag %>
38 38 <%= select_tag 'per_page', options_for_select(@results_per_page_options, @results_per_page), :class => 'select-small'%>
39 39 <%= submit_tag l(:button_apply), :class => 'button-small'%>
40 40 <%= end_form_tag %>
41 41 </td>
42 42 </tr>
43 43 </table>
44 44 <%= start_form_tag({:controller => 'projects', :action => 'move_issues', :id => @project}, :id => 'issues_form' ) %>
45 45 <table class="listTableContent">
46 46
47 47 <tr class="ListHead">
48 48 <td></td>
49 49 <%= sort_header_tag('issues.id', :caption => '#') %>
50 50 <%= sort_header_tag('issue_statuses.name', :caption => l(:field_status)) %>
51 51 <%= sort_header_tag('issues.tracker_id', :caption => l(:field_tracker)) %>
52 52 <th><%=l(:field_subject)%></th>
53 53 <%= sort_header_tag('users.lastname', :caption => l(:field_author)) %>
54 54 <%= sort_header_tag('issues.created_on', :caption => l(:field_created_on)) %>
55 55 <%= sort_header_tag('issues.updated_on', :caption => l(:field_updated_on)) %>
56 56 </tr>
57 57 <% for issue in @issues %>
58 58 <tr bgcolor="#<%= issue.status.html_color %>">
59 59 <td width="15"><%= check_box_tag "issue_ids[]", issue.id %></td>
60 60 <td align="center"><%= link_to issue.long_id, :controller => 'issues', :action => 'show', :id => issue %></td>
61 61 <td align="center"><%= issue.status.name %></td>
62 62 <td align="center"><%= issue.tracker.name %></td>
63 63 <td><%= link_to issue.subject, :controller => 'issues', :action => 'show', :id => issue %></td>
64 64 <td align="center"><%= issue.author.display_name %></td>
65 65 <td align="center"><%= format_time(issue.created_on) %></td>
66 66 <td align="center"><%= format_time(issue.updated_on) %></td>
67 67 </tr>
68 68 <% end %>
69 69 </table>
70 70 <p>
71 71 <%= pagination_links_full @issue_pages %>
72 72 [ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ]
73 73 </p>
74 74 <%= submit_tag l(:button_move) %>
75 75 <%= end_form_tag %> No newline at end of file
@@ -1,7 +1,7
1 1 <h2><%=l(:label_report_plural)%></h2>
2 2
3 <strong><%=@report_title%></strong>
3 <h3><%=@report_title%></h3>
4 4 <%= render :partial => 'details', :locals => { :data => @data, :field_name => @field, :rows => @rows } %>
5 5 <br />
6 6 <%= link_to l(:button_back), :action => 'issue_report' %>
7 7
@@ -1,30 +1,30
1 1 <div class="splitcontentleft">
2 2 <h2><%= $RDM_WELCOME_TITLE || l(:label_home) %></h2>
3 3 <p><%= $RDM_WELCOME_TEXT %></p>
4 4
5 5 <div class="box">
6 6 <h3><%=l(:label_news_latest)%></h3>
7 7 <% for news in @news %>
8 8 <p>
9 9 <b><%= news.title %></b> (<%= link_to_user news.author %> <%= format_time(news.created_on) %> - <%= news.project.name %>)<br />
10 <%= news.summary %><br />
10 <% unless news.summary.empty? %><%= news.summary %><br /><% end %>
11 11 [<%= link_to l(:label_read), :controller => 'news', :action => 'show', :id => news %>]
12 12 </p>
13 13 <hr />
14 14 <% end %>
15 15 </div>
16 16 </div>
17 17
18 18 <div class="splitcontentright">
19 19 <div class="box">
20 20 <h3><%=l(:label_project_latest)%></h3>
21 21 <ul>
22 22 <% for project in @projects %>
23 23 <li>
24 24 <%= link_to project.name, :controller => 'projects', :action => 'show', :id => project %> (<%= format_time(project.created_on) %>)<br />
25 25 <%= project.description %>
26 26 </li>
27 27 <% end %>
28 28 </ul>
29 29 </div>
30 30 </div>
General Comments 0
You need to be logged in to leave comments. Login now