Feature #5125 » roadmap_pdf_export.patch
app/controllers/issues_controller.rb | ||
---|---|---|
120 | 120 |
format.html { render :template => 'issues/show.rhtml' } |
121 | 121 |
format.xml { render :layout => false } |
122 | 122 |
format.atom { render :action => 'changes', :layout => false, :content_type => 'application/atom+xml' } |
123 |
format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") } |
|
123 |
format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf", |
|
124 |
:disposition => 'inline') } |
|
124 | 125 |
end |
125 | 126 |
end |
126 | 127 |
app/controllers/projects_controller.rb | ||
---|---|---|
41 | 41 |
include CustomFieldsHelper |
42 | 42 |
helper :issues |
43 | 43 |
helper IssuesHelper |
44 |
include IssuesHelper |
|
44 | 45 |
helper :queries |
45 | 46 |
include QueriesHelper |
46 | 47 |
helper :repositories |
47 | 48 |
include RepositoriesHelper |
48 | 49 |
include ProjectsHelper |
50 |
include Redmine::Export::PDF |
|
49 | 51 |
|
50 | 52 |
# Lists visible projects |
51 | 53 |
def index |
... | ... | |
310 | 312 |
end |
311 | 313 |
end |
312 | 314 |
@versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?} |
315 | ||
316 |
respond_to do |format| |
|
317 |
format.html { render :template => 'projects/roadmap.rhtml' } |
|
318 |
format.pdf { send_data(versions_to_pdf(@versions, @issues_by_version), |
|
319 |
:type => 'application/pdf', |
|
320 |
:filename => "#{@project.identifier}-roadmap.pdf", |
|
321 |
:disposition => 'inline') } |
|
322 |
end |
|
313 | 323 |
end |
314 | 324 |
|
315 | 325 |
def activity |
app/controllers/versions_controller.rb | ||
---|---|---|
25 | 25 | |
26 | 26 |
helper :custom_fields |
27 | 27 |
helper :projects |
28 |
helper :issues |
|
29 |
include IssuesHelper |
|
30 |
include Redmine::Export::PDF |
|
28 | 31 |
|
29 | 32 |
def show |
33 |
respond_to do |format| |
|
34 |
format.html { render :template => 'versions/show.rhtml' } |
|
35 |
format.pdf { send_data(version_to_pdf(@version), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@version.id}.pdf", |
|
36 |
:disposition => 'inline') } |
|
37 |
end |
|
30 | 38 |
end |
31 | 39 |
|
32 | 40 |
def new |
app/helpers/versions_helper.rb | ||
---|---|---|
16 | 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | 17 | |
18 | 18 |
module VersionsHelper |
19 |
include IssuesHelper |
|
19 | 20 | |
20 | 21 |
STATUS_BY_CRITERIAS = %w(category tracker priority author assigned_to) |
21 | 22 |
|
app/models/issue.rb | ||
---|---|---|
66 | 66 |
named_scope :with_limit, lambda { |limit| { :limit => limit} } |
67 | 67 |
named_scope :on_active_project, :include => [:status, :project, :tracker], |
68 | 68 |
:conditions => ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"] |
69 |
named_scope :for_roadmap, :include => [:status, :project, :tracker], |
|
70 |
:order => "#{Tracker.table_name}.position, #{Issue.table_name}.id" |
|
69 | 71 | |
70 | 72 |
before_create :default_assign |
71 | 73 |
before_save :reschedule_following_issues, :close_duplicates, :update_done_ratio_from_issue_status |
app/views/projects/roadmap.rhtml | ||
---|---|---|
25 | 25 |
<%= call_hook :view_projects_roadmap_version_bottom, :version => version %> |
26 | 26 |
<% end %> |
27 | 27 |
</div> |
28 | ||
29 |
<% other_formats_links do |f| %> |
|
30 |
<%= f.link_to 'PDF' %> |
|
31 |
<% end %> |
|
32 | ||
28 | 33 |
<% end %> |
29 | 34 | |
30 | 35 |
<% content_for :sidebar do %> |
app/views/versions/show.rhtml | ||
---|---|---|
32 | 32 |
<%= render :partial => 'versions/overview', :locals => {:version => @version} %> |
33 | 33 |
<%= render(:partial => "wiki/content", :locals => {:content => @version.wiki_page.content}) if @version.wiki_page %> |
34 | 34 | |
35 |
<% issues = @version.fixed_issues.find(:all, |
|
36 |
:include => [:status, :tracker, :priority], |
|
37 |
:order => "#{Tracker.table_name}.position, #{Issue.table_name}.id") %> |
|
35 |
<% issues = @version.fixed_issues.for_roadmap %> |
|
38 | 36 |
<% if issues.size > 0 %> |
39 | 37 |
<fieldset class="related-issues"><legend><%= l(:label_related_issues) %></legend> |
40 | 38 |
<ul> |
... | ... | |
46 | 44 |
<% end %> |
47 | 45 |
</div> |
48 | 46 | |
47 |
<% other_formats_links do |f| %> |
|
48 |
<%= f.link_to 'PDF' %> |
|
49 |
<% end %> |
|
50 | ||
49 | 51 |
<%= call_hook :view_versions_show_bottom, :version => @version %> |
50 | 52 | |
51 | 53 |
<% html_title @version.name %> |
54 |
lib/redmine/export/pdf.rb | ||
---|---|---|
112 | 112 |
SetX(-30) |
113 | 113 |
Cell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C') |
114 | 114 |
end |
115 | ||
116 |
# Patching the buggy page detection in FPDF that leads to only the last link |
|
117 |
# being really added to the document |
|
118 |
def Link(x, y, w, h, link) |
|
119 |
# Put a link on the page |
|
120 |
@PageLinks[@page]=Array.new unless @PageLinks.has_key?(@page) |
|
121 |
@PageLinks[@page].push([x*@k,@hPt-y*@k,w*@k,h*@k,link]) |
|
122 |
end |
|
123 | ||
115 | 124 |
end |
116 | 125 |
|
117 | 126 |
# Returns a PDF string of a list of issues |
... | ... | |
186 | 195 |
end |
187 | 196 |
|
188 | 197 |
# Returns a PDF string of a single issue |
189 |
def issue_to_pdf(issue) |
|
190 |
pdf = IFPDF.new(current_language) |
|
191 |
pdf.SetTitle("#{issue.project} - ##{issue.tracker} #{issue.id}") |
|
192 |
pdf.AliasNbPages |
|
193 |
pdf.footer_date = format_date(Date.today) |
|
194 |
pdf.AddPage |
|
198 |
def issue_to_pdf(issue, pdf_document = nil) |
|
199 |
# reuse existing PDF document or create a new one |
|
200 |
pdf = pdf_document || IFPDF.new(current_language) |
|
201 |
unless pdf_document |
|
202 |
# PDF document was not given - so we initialize the new document |
|
203 |
pdf.SetTitle("#{issue.project} - #{issue.tracker} ##{issue.id}") |
|
204 |
pdf.AliasNbPages |
|
205 |
pdf.footer_date = format_date(Date.today) |
|
206 |
pdf.AddPage |
|
207 |
end |
|
195 | 208 |
|
196 |
pdf.SetFontStyle('B',11) |
|
197 |
pdf.Cell(190,10, "#{issue.project} - #{issue.tracker} # #{issue.id}: #{issue.subject}") |
|
209 |
pdf.SetFontStyle('B',11) |
|
210 |
pdf.Cell(190,2, "#{issue.project} - #{issue.tracker} ##{issue.id}") |
|
211 |
pdf.Ln |
|
212 |
pdf.SetFontStyle('',11) |
|
213 |
pdf.Cell(190,7, "#{issue.subject}") |
|
214 |
pdf.Ln |
|
215 |
pdf.Cell(190,4, " ") |
|
198 | 216 |
pdf.Ln |
199 | 217 |
|
200 | 218 |
y0 = pdf.GetY |
... | ... | |
255 | 273 |
pdf.SetFontStyle('B',9) |
256 | 274 |
pdf.Cell(35,5, l(:field_description) + ":") |
257 | 275 |
pdf.SetFontStyle('',9) |
258 |
pdf.MultiCell(155,5, @issue.description,"BR")
|
|
276 |
pdf.MultiCell(155,5, issue.description,"BR") |
|
259 | 277 |
|
260 | 278 |
pdf.Line(pdf.GetX, y0, pdf.GetX, pdf.GetY) |
261 | 279 |
pdf.Line(pdf.GetX, pdf.GetY, 170, pdf.GetY) |
... | ... | |
309 | 327 |
pdf.Ln |
310 | 328 |
end |
311 | 329 |
end |
312 |
pdf.Output |
|
330 |
# Print out the pdf if we're not working on external document |
|
331 |
pdf.Output unless pdf_document |
|
313 | 332 |
end |
314 | 333 |
|
315 | 334 |
# Returns a PDF string of a gantt chart |
... | ... | |
489 | 508 |
pdf.Line(15, top, subject_width+g_width, top) |
490 | 509 |
pdf.Output |
491 | 510 |
end |
511 |
|
|
512 |
# Returns a PDF string of a single version |
|
513 |
def version_to_pdf(version, include_issues = true, pdf_document = nil) |
|
514 |
pdf = pdf_document || IFPDF.new(current_language) |
|
515 |
unless pdf_document |
|
516 |
pdf.SetTitle("#{version.project} - #{version.name}") |
|
517 |
pdf.AliasNbPages |
|
518 |
pdf.footer_date = format_date(Date.today) |
|
519 |
pdf.AddPage |
|
520 |
end |
|
521 |
|
|
522 |
pdf.SetFontStyle('B',11) |
|
523 |
pdf.Cell(0,10, "#{version.project} - #{version.name}") |
|
524 |
pdf.Ln |
|
525 | ||
526 |
pdf.SetFontStyle('I',7) |
|
527 |
pdf.Cell(0,1, |
|
528 |
l(:label_x_closed_issues_abbr, :count => version.closed_issues_count) + |
|
529 |
' ('+('%0.0f' % (version.closed_issues_count.to_f / version.fixed_issues.count * 100))+'%), ' + |
|
530 |
l(:label_x_open_issues_abbr, :count => version.open_issues_count) + |
|
531 |
' ('+('%0.0f' % (version.open_issues_count.to_f / version.fixed_issues.count * 100))+'%)' |
|
532 |
) |
|
533 |
pdf.Ln |
|
534 |
pdf.Cell(0,4," ") |
|
535 |
pdf.Ln |
|
536 |
|
|
537 |
issues = version.fixed_issues.for_roadmap |
|
538 |
|
|
539 |
# Collect all created links |
|
540 |
@issues_links ||= {} |
|
541 |
|
|
542 |
# Print issues overview |
|
543 |
pdf.SetFontStyle('', 8) |
|
544 |
issues.each do |issue| |
|
545 |
issue_id = "#{issue.tracker} ##{issue.id}:" |
|
546 |
id_width = pdf.GetStringWidth(issue_id) |
|
547 |
# Create new link |
|
548 |
@issues_links[issue.id] = pdf.AddLink |
|
549 |
if issue.closed? |
|
550 |
pdf.SetTextColor(0xA0, 0xA0, 0xA0) |
|
551 |
pdf.SetDrawColor(0xA0, 0xA0, 0xA0) |
|
552 |
else |
|
553 |
pdf.SetTextColor(0x35, 0x61, 0x8C) |
|
554 |
end |
|
555 |
pdf.Cell(id_width+1, 4, issue_id, 0, 0, 'L', false, @issues_links[issue.id]) |
|
556 |
if issue.closed? |
|
557 |
curx = pdf.GetX |
|
558 |
pdf.Line(curx-1, pdf.GetY+2, curx-id_width, pdf.GetY+2) |
|
559 |
end |
|
560 |
pdf.SetTextColor(0, 0, 0) |
|
561 |
pdf.SetDrawColor(0, 0, 0) |
|
562 |
pdf.Cell(0, 4, issue.subject) |
|
563 |
pdf.Ln |
|
564 |
end |
|
565 |
|
|
566 |
# Print issues details |
|
567 |
issues.each do |issue| |
|
568 |
pdf.AddPage |
|
569 |
pdf.SetLink(@issues_links[issue.id]) |
|
570 |
issue_to_pdf(issue, pdf) |
|
571 |
end if include_issues |
|
572 |
|
|
573 |
pdf.Output unless pdf_document |
|
574 |
end |
|
575 |
|
|
576 |
# Returns a PDF string of all versions (roadmap) |
|
577 |
def versions_to_pdf(versions, issues_by_version) |
|
578 |
pdf = IFPDF.new(current_language) |
|
579 |
pdf.SetTitle(l(:label_roadmap)) |
|
580 |
pdf.AliasNbPages |
|
581 |
pdf.footer_date = format_date(Date.today) |
|
582 |
pdf.AddPage |
|
583 |
|
|
584 |
# Print versions overview |
|
585 |
versions.each do |version| |
|
586 |
version_to_pdf(version, false, pdf) |
|
587 |
pdf.Cell(0, 6, ' ') |
|
588 |
pdf.Ln |
|
589 |
end |
|
590 | ||
591 |
# Print issues details |
|
592 |
versions.each do |version| |
|
593 |
issues_by_version[version].each do |issue| |
|
594 |
pdf.AddPage |
|
595 |
pdf.SetLink(@issues_links[issue.id]) |
|
596 |
issue_to_pdf(issue, pdf) |
|
597 |
end |
|
598 |
end |
|
599 |
|
|
600 |
pdf.Output |
|
601 |
end |
|
492 | 602 |
end |
493 | 603 |
end |
494 | 604 |
end |