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  |