Ported subtasks display with indentation to the new gantt (#7128) and fixed markers alignment.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4534 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
86e17ce74f
commit
525656a490
|
@ -72,6 +72,8 @@ module Redmine
|
|||
@lines = ''
|
||||
@number_of_rows = nil
|
||||
|
||||
@issue_ancestors = []
|
||||
|
||||
@truncated = false
|
||||
if options.has_key?(:max_rows)
|
||||
@max_rows = options[:max_rows]
|
||||
|
@ -213,14 +215,18 @@ module Redmine
|
|||
end
|
||||
|
||||
def render_issues(issues, options={})
|
||||
@issue_ancestors = []
|
||||
|
||||
issues.each do |i|
|
||||
subject_for_issue(i, options) unless options[:only] == :lines
|
||||
line_for_issue(i, options) unless options[:only] == :subjects
|
||||
|
||||
options[:top] += options[:top_increment]
|
||||
@number_of_rows += 1
|
||||
return if abort?
|
||||
break if abort?
|
||||
end
|
||||
|
||||
options[:indent] -= (options[:indent_increment] * @issue_ancestors.size)
|
||||
end
|
||||
|
||||
def render_version(version, options={})
|
||||
|
@ -332,7 +338,12 @@ module Redmine
|
|||
end
|
||||
|
||||
def subject_for_issue(issue, options)
|
||||
case options[:format]
|
||||
while @issue_ancestors.any? && !issue.is_descendant_of?(@issue_ancestors.last)
|
||||
@issue_ancestors.pop
|
||||
options[:indent] -= options[:indent_increment]
|
||||
end
|
||||
|
||||
output = case options[:format]
|
||||
when :html
|
||||
css_classes = ''
|
||||
css_classes << ' issue-overdue' if issue.overdue?
|
||||
|
@ -346,13 +357,20 @@ module Redmine
|
|||
end
|
||||
subject << view.link_to_issue(issue)
|
||||
subject << '</span>'
|
||||
html_subject(options, subject, :css => "issue-subject")
|
||||
html_subject(options, subject, :css => "issue-subject") + "\n"
|
||||
when :image
|
||||
image_subject(options, issue.subject)
|
||||
when :pdf
|
||||
pdf_new_page?(options)
|
||||
pdf_subject(options, issue.subject)
|
||||
end
|
||||
|
||||
unless issue.leaf?
|
||||
@issue_ancestors << issue
|
||||
options[:indent] += options[:indent_increment]
|
||||
end
|
||||
|
||||
output
|
||||
end
|
||||
|
||||
def line_for_issue(issue, options)
|
||||
|
@ -363,7 +381,7 @@ module Redmine
|
|||
|
||||
case options[:format]
|
||||
when :html
|
||||
html_task(options, coords, :css => "task " + (issue.leaf? ? 'leaf' : 'parent'), :label => label, :issue => issue)
|
||||
html_task(options, coords, :css => "task " + (issue.leaf? ? 'leaf' : 'parent'), :label => label, :issue => issue, :markers => !issue.leaf?)
|
||||
when :image
|
||||
image_task(options, coords, :label => label)
|
||||
when :pdf
|
||||
|
@ -655,12 +673,34 @@ module Redmine
|
|||
|
||||
# Sorts a collection of issues by start_date, due_date, id for gantt rendering
|
||||
def sort_issues!(issues)
|
||||
issues.sort! do |a, b|
|
||||
cmp = 0
|
||||
cmp = (a.start_date <=> b.start_date) if a.start_date? && b.start_date?
|
||||
cmp = (a.due_date <=> b.due_date) if cmp == 0 && a.due_date? && b.due_date?
|
||||
cmp = (a.id <=> b.id) if cmp == 0
|
||||
cmp
|
||||
issues.sort! { |a, b| gantt_issue_compare(a, b, issues) }
|
||||
end
|
||||
|
||||
def gantt_issue_compare(x, y, issues)
|
||||
if x.parent_id == y.parent_id
|
||||
gantt_start_compare(x, y)
|
||||
elsif x.is_ancestor_of?(y)
|
||||
-1
|
||||
elsif y.is_ancestor_of?(x)
|
||||
1
|
||||
else
|
||||
ax = issues.select {|i| i.is_a?(Issue) && i.is_ancestor_of?(x) && !i.is_ancestor_of?(y) }.sort_by(&:lft).first
|
||||
ay = issues.select {|i| i.is_a?(Issue) && i.is_ancestor_of?(y) && !i.is_ancestor_of?(x) }.sort_by(&:lft).first
|
||||
if ax.nil? && ay.nil?
|
||||
gantt_start_compare(x, y)
|
||||
else
|
||||
gantt_issue_compare(ax || x, ay || y, issues)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def gantt_start_compare(x, y)
|
||||
if x.start_date.nil?
|
||||
-1
|
||||
elsif y.start_date.nil?
|
||||
1
|
||||
else
|
||||
x.start_date <=> y.start_date
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -733,12 +773,12 @@ module Redmine
|
|||
output << "<div style='top:#{ params[:top] }px;left:#{ coords[:start] }px;width:15px;' class='#{options[:css]} marker starting'> </div>"
|
||||
end
|
||||
if coords[:end]
|
||||
output << "<div style='top:#{ params[:top] }px;left:#{ coords[:end] }px;width:15px;' class='#{options[:css]} marker ending'> </div>"
|
||||
output << "<div style='top:#{ params[:top] }px;left:#{ coords[:end] + params[:zoom] }px;width:15px;' class='#{options[:css]} marker ending'> </div>"
|
||||
end
|
||||
end
|
||||
# Renders the label on the right
|
||||
if options[:label]
|
||||
output << "<div style='top:#{ params[:top] }px;left:#{ (coords[:bar_end] || 0) + 5 }px;' class='#{options[:css]} label'>"
|
||||
output << "<div style='top:#{ params[:top] }px;left:#{ (coords[:bar_end] || 0) + 8 }px;' class='#{options[:css]} label'>"
|
||||
output << options[:label]
|
||||
output << "</div>"
|
||||
end
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 224 B |
|
@ -799,20 +799,20 @@ background-image:url('../images/close_hl.png');
|
|||
.task_done { background:#00c600 url(../images/task_done.png); border: 1px solid #00c600; }
|
||||
.task_todo { background:#aaa url(../images/task_todo.png); border: 1px solid #aaa; }
|
||||
|
||||
.task_todo.parent { background: #888; border: 1px solid #888; height: 6px;}
|
||||
.task_todo.parent { background: #888; border: 1px solid #888; height: 3px;}
|
||||
.task_late.parent, .task_done.parent { height: 3px;}
|
||||
.task_todo.parent .left { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -5px; left: 0px; top: -1px;}
|
||||
.task_todo.parent .right { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-right: -5px; right: 0px; top: -1px;}
|
||||
.task.parent.marker.starting { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; left: 0px; top: -1px;}
|
||||
.task.parent.marker.ending { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; right: 0px; top: -1px;}
|
||||
|
||||
.version.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;}
|
||||
.version.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;}
|
||||
.version.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;}
|
||||
.version.marker { background-image:url(../images/version_marker.png); background-repeat: no-repeat; border: 0; }
|
||||
.version.marker { background-image:url(../images/version_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; }
|
||||
|
||||
.project.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;}
|
||||
.project.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;}
|
||||
.project.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;}
|
||||
.project.marker { background-image:url(../images/project_marker.png); background-repeat: no-repeat; border: 0; }
|
||||
.project.marker { background-image:url(../images/project_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; }
|
||||
|
||||
.version-behind-schedule a, .issue-behind-schedule a {color: #f66914;}
|
||||
.version-overdue a, .issue-overdue a, .project-overdue a {color: #f00;}
|
||||
|
|
|
@ -158,39 +158,63 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
|
|||
:done_ratio => 30,
|
||||
:start_date => Date.yesterday,
|
||||
:due_date => 1.week.from_now.to_date)
|
||||
@project.issues << @issue
|
||||
|
||||
@response.body = @gantt.subjects
|
||||
@project.issues << @issue
|
||||
end
|
||||
|
||||
|
||||
context "project" do
|
||||
should "be rendered" do
|
||||
@response.body = @gantt.subjects
|
||||
assert_select "div.project-name a", /#{@project.name}/
|
||||
end
|
||||
|
||||
|
||||
should "have an indent of 4" do
|
||||
@response.body = @gantt.subjects
|
||||
assert_select "div.project-name[style*=left:4px]"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
context "version" do
|
||||
should "be rendered" do
|
||||
@response.body = @gantt.subjects
|
||||
assert_select "div.version-name a", /#{@version.name}/
|
||||
end
|
||||
|
||||
|
||||
should "be indented 24 (one level)" do
|
||||
@response.body = @gantt.subjects
|
||||
assert_select "div.version-name[style*=left:24px]"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
context "issue" do
|
||||
should "be rendered" do
|
||||
@response.body = @gantt.subjects
|
||||
assert_select "div.issue-subject", /#{@issue.subject}/
|
||||
end
|
||||
|
||||
|
||||
should "be indented 44 (two levels)" do
|
||||
@response.body = @gantt.subjects
|
||||
assert_select "div.issue-subject[style*=left:44px]"
|
||||
end
|
||||
|
||||
context "with subtasks" do
|
||||
setup do
|
||||
attrs = {:project => @project, :tracker => @tracker, :fixed_version => @version}
|
||||
@child1 = Issue.generate!(attrs.merge(:subject => 'child1', :parent_issue_id => @issue.id, :start_date => Date.yesterday, :due_date => 2.day.from_now.to_date))
|
||||
@child2 = Issue.generate!(attrs.merge(:subject => 'child2', :parent_issue_id => @issue.id, :start_date => Date.today, :due_date => 1.week.from_now.to_date))
|
||||
@grandchild = Issue.generate!(attrs.merge(:subject => 'grandchild', :parent_issue_id => @child1.id, :start_date => Date.yesterday, :due_date => 2.day.from_now.to_date))
|
||||
end
|
||||
|
||||
should "indent subtasks" do
|
||||
@response.body = @gantt.subjects
|
||||
# parent task 44px
|
||||
assert_select "div.issue-subject[style*=left:44px]", /#{@issue.subject}/
|
||||
# children 64px
|
||||
assert_select "div.issue-subject[style*=left:64px]", /child1/
|
||||
assert_select "div.issue-subject[style*=left:64px]", /child2/
|
||||
# grandchild 84px
|
||||
assert_select "div.issue-subject[style*=left:84px]", /grandchild/, @response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -379,7 +403,7 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
|
|||
|
||||
should "appear at the end of the date range" do
|
||||
@response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
|
||||
assert_select "div.project.ending[style*=left:84px]", true, @response.body
|
||||
assert_select "div.project.ending[style*=left:88px]", true, @response.body
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -546,7 +570,7 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
|
|||
|
||||
should "appear at the end of the date range" do
|
||||
@response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
|
||||
assert_select "div.version.ending[style*=left:84px]", true, @response.body
|
||||
assert_select "div.version.ending[style*=left:88px]", true, @response.body
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue