Adds subtasking (#443) including:
* priority, start/due dates, progress, estimate, spent time roll-up to parent issues * descendant issues tree displayed on the issue view with context menu support * issue tree display on the gantt chart * issue tree copy on project copy * unlimited nesting Defining subtasks requires the new permission 'Manage subtasks'. Subtasks can not belong to a different project than the parent task. Implementation is based on scoped nested sets for fast reads and updates. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3573 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
+2
-1
@@ -47,13 +47,14 @@ Redmine::AccessControl.map do |map|
|
||||
map.permission :manage_categories, {:projects => :settings, :issue_categories => [:new, :edit, :destroy]}, :require => :member
|
||||
# Issues
|
||||
map.permission :view_issues, {:projects => :roadmap,
|
||||
:issues => [:index, :changes, :show, :context_menu],
|
||||
:issues => [:index, :changes, :show, :context_menu, :auto_complete],
|
||||
:versions => [:show, :status_by],
|
||||
:queries => :index,
|
||||
:reports => [:issue_report, :issue_report_details]}
|
||||
map.permission :add_issues, {:issues => [:new, :update_form]}
|
||||
map.permission :edit_issues, {:issues => [:edit, :update, :reply, :bulk_edit, :update_form]}
|
||||
map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
|
||||
map.permission :manage_subtasks, {}
|
||||
map.permission :add_issue_notes, {:issues => [:edit, :update, :reply]}
|
||||
map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
|
||||
map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
|
||||
|
||||
@@ -53,6 +53,7 @@ module Redmine
|
||||
:add_issues,
|
||||
:edit_issues,
|
||||
:manage_issue_relations,
|
||||
:manage_subtasks,
|
||||
:add_issue_notes,
|
||||
:save_queries,
|
||||
:view_gantt,
|
||||
|
||||
@@ -52,8 +52,29 @@ module Redmine
|
||||
@date_to = (@date_from >> @months) - 1
|
||||
end
|
||||
|
||||
|
||||
def events=(e)
|
||||
@events = e.sort {|x,y| x.start_date <=> y.start_date }
|
||||
@events = e
|
||||
# Adds all ancestors
|
||||
root_ids = e.select {|i| i.is_a?(Issue) && i.parent_id? }.collect(&:root_id).uniq
|
||||
if root_ids.any?
|
||||
# Retrieves all nodes
|
||||
parents = Issue.find_all_by_root_id(root_ids, :conditions => ["rgt - lft > 1"])
|
||||
# Only add ancestors
|
||||
@events += parents.select {|p| @events.detect {|i| i.is_a?(Issue) && p.is_ancestor_of?(i)}}
|
||||
end
|
||||
@events.uniq!
|
||||
# Sort issues by hierarchy and start dates
|
||||
@events.sort! {|x,y|
|
||||
if x.is_a?(Issue) && y.is_a?(Issue)
|
||||
gantt_issue_compare(x, y, @events)
|
||||
else
|
||||
gantt_start_compare(x, y)
|
||||
end
|
||||
}
|
||||
# Removes issues that have no start or end date
|
||||
@events.reject! {|i| i.is_a?(Issue) && (i.start_date.nil? || i.due_before.nil?) }
|
||||
@events
|
||||
end
|
||||
|
||||
def params
|
||||
@@ -218,6 +239,36 @@ module Redmine
|
||||
imgl.format = format
|
||||
imgl.to_blob
|
||||
end if Object.const_defined?(:Magick)
|
||||
|
||||
private
|
||||
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user