Gantt: do not ignore project filter (#7000, #7352), do not display empty projects/versions, and display shared versions used in other projects (#5817, #6476, #6604).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5077 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
b1cc8511c7
commit
ec8d9a7911
|
@ -1,5 +1,5 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2008 Jean-Philippe Lang
|
||||
# Copyright (C) 2006-2011 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
@ -98,48 +98,22 @@ module Redmine
|
|||
common_params.merge({:year => (date_from >> months).year, :month => (date_from >> months).month, :zoom => zoom, :months => months })
|
||||
end
|
||||
|
||||
### Extracted from the HTML view/helpers
|
||||
# Returns the number of rows that will be rendered on the Gantt chart
|
||||
def number_of_rows
|
||||
return @number_of_rows if @number_of_rows
|
||||
|
||||
rows = if @project
|
||||
number_of_rows_on_project(@project)
|
||||
else
|
||||
Project.roots.visible.has_module('issue_tracking').inject(0) do |total, project|
|
||||
total += number_of_rows_on_project(project)
|
||||
end
|
||||
end
|
||||
|
||||
rows = projects.inject(0) {|total, p| total += number_of_rows_on_project(p)}
|
||||
rows > @max_rows ? @max_rows : rows
|
||||
end
|
||||
|
||||
# Returns the number of rows that will be used to list a project on
|
||||
# the Gantt chart. This will recurse for each subproject.
|
||||
def number_of_rows_on_project(project)
|
||||
# Remove the project requirement for Versions because it will
|
||||
# restrict issues to only be on the current project. This
|
||||
# ends up missing issues which are assigned to shared versions.
|
||||
@query.project = nil if @query.project
|
||||
return 0 unless projects.include?(project)
|
||||
|
||||
# One Root project
|
||||
count = 1
|
||||
# Issues without a Version
|
||||
count += project.issues.for_gantt.without_version.with_query(@query).count
|
||||
|
||||
# Versions
|
||||
count += project.versions.count
|
||||
|
||||
# Issues on the Versions
|
||||
project.versions.each do |version|
|
||||
count += version.fixed_issues.for_gantt.with_query(@query).count
|
||||
end
|
||||
|
||||
# Subprojects
|
||||
project.children.visible.has_module('issue_tracking').each do |subproject|
|
||||
count += number_of_rows_on_project(subproject)
|
||||
end
|
||||
|
||||
count += project_issues(project).size
|
||||
count += project_versions(project).size
|
||||
count
|
||||
end
|
||||
|
||||
|
@ -155,21 +129,61 @@ module Redmine
|
|||
@lines
|
||||
end
|
||||
|
||||
# Returns issues that will be rendered
|
||||
def issues
|
||||
@issues ||= @query.issues(
|
||||
:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
|
||||
:order => "#{Project.table_name}.lft ASC, #{Issue.table_name}.id ASC",
|
||||
:limit => @max_rows
|
||||
)
|
||||
end
|
||||
|
||||
# Return all the project nodes that will be displayed
|
||||
def projects
|
||||
return @projects if @projects
|
||||
|
||||
ids = issues.collect(&:project).uniq.collect(&:id)
|
||||
if ids.any?
|
||||
# All issues projects and their visible ancestors
|
||||
@projects = Project.visible.all(
|
||||
:joins => "LEFT JOIN #{Project.table_name} child ON #{Project.table_name}.lft <= child.lft AND #{Project.table_name}.rgt >= child.rgt",
|
||||
:conditions => ["child.id IN (?)", ids],
|
||||
:order => "#{Project.table_name}.lft ASC"
|
||||
).uniq
|
||||
else
|
||||
@projects = []
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the issues that belong to +project+
|
||||
def project_issues(project)
|
||||
@issues_by_project ||= issues.group_by(&:project)
|
||||
@issues_by_project[project] || []
|
||||
end
|
||||
|
||||
# Returns the distinct versions of the issues that belong to +project+
|
||||
def project_versions(project)
|
||||
project_issues(project).collect(&:fixed_version).compact.uniq
|
||||
end
|
||||
|
||||
# Returns the issues that belong to +project+ and are assigned to +version+
|
||||
def version_issues(project, version)
|
||||
project_issues(project).select {|issue| issue.fixed_version == version}
|
||||
end
|
||||
|
||||
def render(options={})
|
||||
options = {:indent => 4, :render => :subject, :format => :html}.merge(options)
|
||||
options = {:top => 0, :top_increment => 20, :indent_increment => 20, :render => :subject, :format => :html}.merge(options)
|
||||
indent = options[:indent] || 4
|
||||
|
||||
@subjects = '' unless options[:only] == :lines
|
||||
@lines = '' unless options[:only] == :subjects
|
||||
@number_of_rows = 0
|
||||
|
||||
if @project
|
||||
render_project(@project, options)
|
||||
else
|
||||
Project.roots.visible.has_module('issue_tracking').each do |project|
|
||||
Project.project_tree(projects) do |project, level|
|
||||
options[:indent] = indent + level * options[:indent_increment]
|
||||
render_project(project, options)
|
||||
break if abort?
|
||||
end
|
||||
end
|
||||
|
||||
@subjects_rendered = true unless options[:only] == :lines
|
||||
@lines_rendered = true unless options[:only] == :subjects
|
||||
|
@ -178,10 +192,6 @@ module Redmine
|
|||
end
|
||||
|
||||
def render_project(project, options={})
|
||||
options[:top] = 0 unless options.key? :top
|
||||
options[:indent_increment] = 20 unless options.key? :indent_increment
|
||||
options[:top_increment] = 20 unless options.key? :top_increment
|
||||
|
||||
subject_for_project(project, options) unless options[:only] == :lines
|
||||
line_for_project(project, options) unless options[:only] == :subjects
|
||||
|
||||
|
@ -190,26 +200,18 @@ module Redmine
|
|||
@number_of_rows += 1
|
||||
return if abort?
|
||||
|
||||
# Second, Issues without a version
|
||||
issues = project.issues.for_gantt.without_version.with_query(@query).all(:limit => current_limit)
|
||||
issues = project_issues(project).select {|i| i.fixed_version.nil?}
|
||||
sort_issues!(issues)
|
||||
if issues
|
||||
render_issues(issues, options)
|
||||
return if abort?
|
||||
end
|
||||
|
||||
# Third, Versions
|
||||
project.versions.sort.each do |version|
|
||||
render_version(version, options)
|
||||
return if abort?
|
||||
versions = project_versions(project)
|
||||
versions.each do |version|
|
||||
render_version(project, version, options)
|
||||
end
|
||||
|
||||
# Fourth, subprojects
|
||||
project.children.visible.has_module('issue_tracking').each do |project|
|
||||
render_project(project, options)
|
||||
return if abort?
|
||||
end unless project.leaf?
|
||||
|
||||
# Remove indent to hit the next sibling
|
||||
options[:indent] -= options[:indent_increment]
|
||||
end
|
||||
|
@ -229,7 +231,7 @@ module Redmine
|
|||
options[:indent] -= (options[:indent_increment] * @issue_ancestors.size)
|
||||
end
|
||||
|
||||
def render_version(version, options={})
|
||||
def render_version(project, version, options={})
|
||||
# Version header
|
||||
subject_for_version(version, options) unless options[:only] == :lines
|
||||
line_for_version(version, options) unless options[:only] == :subjects
|
||||
|
@ -238,12 +240,7 @@ module Redmine
|
|||
@number_of_rows += 1
|
||||
return if abort?
|
||||
|
||||
# Remove the project requirement for Versions because it will
|
||||
# restrict issues to only be on the current project. This
|
||||
# ends up missing issues which are assigned to shared versions.
|
||||
@query.project = nil if @query.project
|
||||
|
||||
issues = version.fixed_issues.for_gantt.with_query(@query).all(:limit => current_limit)
|
||||
issues = version_issues(project, version)
|
||||
if issues
|
||||
sort_issues!(issues)
|
||||
# Indent issues
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# redMine - project management software
|
||||
# Copyright (C) 2006-2008 Jean-Philippe Lang
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2011 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
@ -96,14 +96,8 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
|
|||
create_gantt
|
||||
end
|
||||
|
||||
should "clear the @query.project so cross-project issues and versions can be counted" do
|
||||
assert @gantt.query.project
|
||||
@gantt.number_of_rows_on_project(@project)
|
||||
assert_nil @gantt.query.project
|
||||
end
|
||||
|
||||
should "count 1 for the project itself" do
|
||||
assert_equal 1, @gantt.number_of_rows_on_project(@project)
|
||||
should "count 0 for an empty the project" do
|
||||
assert_equal 0, @gantt.number_of_rows_on_project(@project)
|
||||
end
|
||||
|
||||
should "count the number of issues without a version" do
|
||||
|
@ -111,12 +105,6 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
|
|||
assert_equal 2, @gantt.number_of_rows_on_project(@project)
|
||||
end
|
||||
|
||||
should "count the number of versions" do
|
||||
@project.versions << Version.generate!
|
||||
@project.versions << Version.generate!
|
||||
assert_equal 3, @gantt.number_of_rows_on_project(@project)
|
||||
end
|
||||
|
||||
should "count the number of issues on versions, including cross-project" do
|
||||
version = Version.generate!
|
||||
@project.versions << version
|
||||
|
@ -124,21 +112,6 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
|
|||
|
||||
assert_equal 3, @gantt.number_of_rows_on_project(@project)
|
||||
end
|
||||
|
||||
should "recursive and count the number of rows on each subproject" do
|
||||
@project.versions << Version.generate! # +1
|
||||
|
||||
@subproject = Project.generate!(:enabled_module_names => ['issue_tracking']) # +1
|
||||
@subproject.set_parent!(@project)
|
||||
@subproject.issues << Issue.generate_for_project!(@subproject) # +1
|
||||
@subproject.issues << Issue.generate_for_project!(@subproject) # +1
|
||||
|
||||
@subsubproject = Project.generate!(:enabled_module_names => ['issue_tracking']) # +1
|
||||
@subsubproject.set_parent!(@subproject)
|
||||
@subsubproject.issues << Issue.generate_for_project!(@subsubproject) # +1
|
||||
|
||||
assert_equal 7, @gantt.number_of_rows_on_project(@project) # +1 for self
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: more of an integration test
|
||||
|
@ -183,6 +156,18 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
|
|||
@response.body = @gantt.subjects
|
||||
assert_select "div.version-name[style*=left:24px]"
|
||||
end
|
||||
|
||||
context "without assigned issues" do
|
||||
setup do
|
||||
@version = Version.generate!(:effective_date => 2.week.from_now.to_date, :sharing => 'none', :name => 'empty_version')
|
||||
@project.versions << @version
|
||||
end
|
||||
|
||||
should "not be rendered" do
|
||||
@response.body = @gantt.subjects
|
||||
assert_select "div.version-name a", :text => /#{@version.name}/, :count => 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "issue" do
|
||||
|
@ -196,6 +181,31 @@ class Redmine::Helpers::GanttTest < ActiveSupport::TestCase
|
|||
assert_select "div.issue-subject[style*=left:44px]"
|
||||
end
|
||||
|
||||
context "assigned to a shared version of another project" do
|
||||
setup do
|
||||
p = Project.generate!
|
||||
p.trackers << @tracker
|
||||
p.enabled_module_names = [:issue_tracking]
|
||||
@shared_version = Version.generate!(:sharing => 'system')
|
||||
p.versions << @shared_version
|
||||
# Reassign the issue to a shared version of another project
|
||||
|
||||
@issue = Issue.generate!(:fixed_version => @shared_version,
|
||||
:subject => "gantt#assigned_to_shared_version",
|
||||
:tracker => @tracker,
|
||||
:project => @project,
|
||||
:done_ratio => 30,
|
||||
:start_date => Date.yesterday,
|
||||
:due_date => 1.week.from_now.to_date)
|
||||
@project.issues << @issue
|
||||
end
|
||||
|
||||
should "be rendered" do
|
||||
@response.body = @gantt.subjects
|
||||
assert_select "div.issue-subject", /#{@issue.subject}/
|
||||
end
|
||||
end
|
||||
|
||||
context "with subtasks" do
|
||||
setup do
|
||||
attrs = {:project => @project, :tracker => @tracker, :fixed_version => @version}
|
||||
|
|
Loading…
Reference in New Issue