Gantt: fixes progress width in some cases and start code cleaning.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4520 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2010-12-17 12:24:11 +00:00
parent 1c3823cbb0
commit 27f76d20ce
2 changed files with 90 additions and 52 deletions

View File

@ -588,53 +588,22 @@ module Redmine
case options[:format] case options[:format]
when :html when :html
output = '' output = ''
# Handle nil start_dates, rare but can happen.
i_start_date = if issue.start_date && issue.start_date >= self.date_from
issue.start_date
else
self.date_from
end
i_end_date = ((issue.due_before && issue.due_before <= self.date_to) ? issue.due_before : self.date_to )
i_done_date = i_start_date + ((issue.due_before - i_start_date+1)*issue.done_ratio/100).floor
i_done_date = (i_done_date <= self.date_from ? self.date_from : i_done_date )
i_done_date = (i_done_date >= self.date_to ? self.date_to : i_done_date )
i_late_date = [i_end_date, Date.today].min if i_start_date < Date.today
i_left = ((i_start_date - self.date_from)*options[:zoom]).floor
i_width = ((i_end_date - i_start_date + 1)*options[:zoom]).floor - 2 # total width of the issue (- 2 for left and right borders)
d_width = ((i_done_date - i_start_date)*options[:zoom]).floor - 2 # done width
l_width = i_late_date ? ((i_late_date - i_start_date+1)*options[:zoom]).floor - 2 : 0 # delay width
css = "task " + (issue.leaf? ? 'leaf' : 'parent') css = "task " + (issue.leaf? ? 'leaf' : 'parent')
# Make sure that negative i_left and i_width don't coords = coordinates(issue.start_date, issue.due_before, issue.done_ratio, options[:zoom])
# overflow the subject if coords[:bar_start] && coords[:bar_end]
if i_width > 0 output << html_task(options[:top], coords, css)
output << "<div style='top:#{ options[:top] }px;left:#{ i_left }px;width:#{ i_width }px;' class='#{css} task_todo'>&nbsp;</div>"
end
if l_width > 0
output << "<div style='top:#{ options[:top] }px;left:#{ i_left }px;width:#{ l_width }px;' class='#{css} task_late'>&nbsp;</div>"
end
if d_width > 0
output<< "<div style='top:#{ options[:top] }px;left:#{ i_left }px;width:#{ d_width }px;' class='#{css} task_done'>&nbsp;</div>"
end
# Display the status even if it's floated off to the left output << "<div class='tooltip' style='position: absolute;top:#{ options[:top] }px;left:#{ coords[:bar_start] }px;width:#{ coords[:bar_end] - coords[:bar_start] }px;height:12px;'>"
status_px = i_left + i_width + 5
status_px = 5 if status_px <= 0
output << "<div style='top:#{ options[:top] }px;left:#{ status_px }px;' class='#{css} label issue-name'>"
output << issue.status.name
output << ' '
output << (issue.done_ratio).to_i.to_s
output << "%"
output << "</div>"
output << "<div class='tooltip' style='position: absolute;top:#{ options[:top] }px;left:#{ i_left }px;width:#{ i_width }px;height:12px;'>"
output << '<span class="tip">' output << '<span class="tip">'
output << view.render_issue_tooltip(issue) output << view.render_issue_tooltip(issue)
output << "</span></div>" output << "</span></div>"
end
output << "<div style='top:#{ options[:top] }px;left:#{ (coords[:bar_end] || 0) + 5 }px;' class='#{css} label issue-name'>"
output << "#{ issue.status.name } #{ issue.done_ratio }%"
output << "</div>"
@lines << output @lines << output
output output
@ -966,6 +935,54 @@ module Redmine
private private
def coordinates(start_date, end_date, progress, zoom=nil)
zoom ||= @zoom
coords = {}
if start_date && end_date && start_date < self.date_to && end_date > self.date_from
if start_date > self.date_from
coords[:start] = start_date - self.date_from
coords[:bar_start] = start_date - self.date_from
else
coords[:bar_start] = 0
end
if end_date < self.date_to
coords[:end] = end_date - self.date_from
coords[:bar_end] = end_date - self.date_from + 1
else
coords[:bar_end] = self.date_to - self.date_from + 1
end
if progress
progress_date = start_date + (end_date - start_date) * (progress / 100.0)
if progress_date > self.date_from && progress_date > start_date
if progress_date < self.date_to
coords[:bar_progress_end] = progress_date - self.date_from + 1
else
coords[:bar_progress_end] = self.date_to - self.date_from + 1
end
end
if progress_date < Date.today
late_date = [Date.today, end_date].min
if late_date > self.date_from && late_date > start_date
if late_date < self.date_to
coords[:bar_late_end] = late_date - self.date_from + 1
else
coords[:bar_late_end] = self.date_to - self.date_from + 1
end
end
end
end
end
# Transforms dates into pixels witdh
coords.keys.each do |key|
coords[key] = (coords[key] * zoom).floor
end
coords
end
# Sorts a collection of issues by start_date, due_date, id for gantt rendering # Sorts a collection of issues by start_date, due_date, id for gantt rendering
def sort_issues!(issues) def sort_issues!(issues)
issues.sort! do |a, b| issues.sort! do |a, b|
@ -999,6 +1016,19 @@ module Redmine
options[:pdf].Line(15, options[:top] - 0.1, PDF::TotalWidth, options[:top] - 0.1) options[:pdf].Line(15, options[:top] - 0.1, PDF::TotalWidth, options[:top] - 0.1)
end end
end end
def html_task(top, coords, css)
output = "<div style='top:#{ top }px;left:#{ coords[:bar_start] }px;width:#{ coords[:bar_end] - coords[:bar_start] - 2}px;' class='#{css} task_todo'>&nbsp;</div>"
if coords[:bar_late_end]
output << "<div style='top:#{ top }px;left:#{ coords[:bar_start] }px;width:#{ coords[:bar_late_end] - coords[:bar_start] - 2}px;' class='#{css} task_late'>&nbsp;</div>"
end
if coords[:bar_progress_end]
output << "<div style='top:#{ top }px;left:#{ coords[:bar_start] }px;width:#{ coords[:bar_progress_end] - coords[:bar_start] - 2}px;' class='#{css} task_done'>&nbsp;</div>"
end
output
end
end end
end end
end end

View File

@ -59,8 +59,8 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
@gantt.project = @project @gantt.project = @project
@gantt.query = Query.generate_default!(:project => @project) @gantt.query = Query.generate_default!(:project => @project)
@gantt.view = build_view @gantt.view = build_view
@gantt.instance_variable_set('@date_from', 2.weeks.ago.to_date) @gantt.instance_variable_set('@date_from', options[:date_from] || 2.weeks.ago.to_date)
@gantt.instance_variable_set('@date_to', 2.weeks.from_now.to_date) @gantt.instance_variable_set('@date_to', options[:date_to] || 2.weeks.from_now.to_date)
end end
context "#number_of_rows" do context "#number_of_rows" do
@ -636,7 +636,7 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
:tracker => @tracker, :tracker => @tracker,
:project => @project, :project => @project,
:done_ratio => 30, :done_ratio => 30,
:start_date => Date.yesterday, :start_date => 1.week.ago.to_date,
:due_date => 1.week.from_now.to_date) :due_date => 1.week.from_now.to_date)
@project.issues << @issue @project.issues << @issue
end end
@ -645,12 +645,12 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
context "todo line" do context "todo line" do
should "start from the starting point on the left" do should "start from the starting point on the left" do
@response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
assert_select "div.task_todo[style*=left:52px]" assert_select "div.task_todo[style*=left:28px]", true, @response.body
end end
should "be the total width of the issue" do should "be the total width of the issue" do
@response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
assert_select "div.task_todo[style*=width:34px]" assert_select "div.task_todo[style*=width:58px]", true, @response.body
end end
end end
@ -658,24 +658,32 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
context "late line" do context "late line" do
should "start from the starting point on the left" do should "start from the starting point on the left" do
@response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
assert_select "div.task_late[style*=left:52px]" assert_select "div.task_late[style*=left:28px]", true, @response.body
end end
should "be the total delayed width of the issue" do should "be the total delayed width of the issue" do
@response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
assert_select "div.task_late[style*=width:6px]" assert_select "div.task_late[style*=width:30px]", true, @response.body
end end
end end
context "done line" do context "done line" do
should "start from the starting point on the left" do should "start from the starting point on the left" do
@response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
assert_select "div.task_done[style*=left:52px]" assert_select "div.task_done[style*=left:28px]", true, @response.body
end end
should "Be the total done width of the issue" do should "Be the total done width of the issue" do
@response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
assert_select "div.task_done[style*=left:52px]" assert_select "div.task_done[style*=width:18px]", true, @response.body
end
should "not be the total done width if the chart starts after issue start date" do
create_gantt(@project, :date_from => 5.days.ago.to_date)
@response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
assert_select "div.task_done[style*=left:0px]", true, @response.body
assert_select "div.task_done[style*=width:10px]", true, @response.body
end end
end end
@ -684,7 +692,7 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
@gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date) @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date)
@response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4}) @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
assert_select "div.issue-name" assert_select "div.issue-name", true, @response.body
end end
should "show the issue status" do should "show the issue status" do