Adds workflow copy functionality (#1727).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3154 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang
2009-12-12 10:06:07 +00:00
parent ddeaf9da96
commit 5c6ce51ec9
13 changed files with 175 additions and 21 deletions
+23
View File
@@ -42,4 +42,27 @@ class WorkflowsController < ApplicationController
@trackers = Tracker.find(:all, :order => 'position')
@statuses = IssueStatus.find(:all, :order => 'position')
end
def copy
@trackers = Tracker.find(:all, :order => 'position')
@roles = Role.find(:all, :order => 'builtin, position')
@source_tracker = params[:source_tracker_id].blank? ? nil : Tracker.find_by_id(params[:source_tracker_id])
@source_role = params[:source_role_id].blank? ? nil : Role.find_by_id(params[:source_role_id])
@target_trackers = params[:target_tracker_ids].blank? ? nil : Tracker.find_all_by_id(params[:target_tracker_ids])
@target_roles = params[:target_role_ids].blank? ? nil : Role.find_all_by_id(params[:target_role_ids])
if request.post?
if params[:source_tracker_id].blank? || params[:source_role_id].blank? || (@source_tracker.nil? && @source_role.nil?)
flash.now[:error] = l(:error_workflow_copy_source)
elsif @target_trackers.nil? || @target_roles.nil?
flash.now[:error] = l(:error_workflow_copy_target)
else
Workflow.copy(@source_tracker, @source_role, @target_trackers, @target_roles)
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'copy', :source_tracker_id => @source_tracker, :source_role_id => @source_role
end
end
end
end
+2 -8
View File
@@ -28,14 +28,8 @@ class Role < ActiveRecord::Base
before_destroy :check_deletable
has_many :workflows, :dependent => :delete_all do
def copy(role)
raise "Can not copy workflow from a #{role.class}" unless role.is_a?(Role)
raise "Can not copy workflow from/to an unsaved role" if proxy_owner.new_record? || role.new_record?
clear
connection.insert "INSERT INTO #{Workflow.table_name} (tracker_id, old_status_id, new_status_id, role_id)" +
" SELECT tracker_id, old_status_id, new_status_id, #{proxy_owner.id}" +
" FROM #{Workflow.table_name}" +
" WHERE role_id = #{role.id}"
def copy(source_role)
Workflow.copy(nil, source_role, nil, proxy_owner)
end
end
+2 -8
View File
@@ -19,14 +19,8 @@ class Tracker < ActiveRecord::Base
before_destroy :check_integrity
has_many :issues
has_many :workflows, :dependent => :delete_all do
def copy(tracker)
raise "Can not copy workflow from a #{tracker.class}" unless tracker.is_a?(Tracker)
raise "Can not copy workflow from/to an unsaved tracker" if proxy_owner.new_record? || tracker.new_record?
clear
connection.insert "INSERT INTO #{Workflow.table_name} (tracker_id, old_status_id, new_status_id, role_id)" +
" SELECT #{proxy_owner.id}, old_status_id, new_status_id, role_id" +
" FROM #{Workflow.table_name}" +
" WHERE tracker_id = #{tracker.id}"
def copy(source_tracker)
Workflow.copy(source_tracker, nil, proxy_owner, nil)
end
end
+46
View File
@@ -51,4 +51,50 @@ class Workflow < ActiveRecord::Base
uniq.
sort
end
# Copies workflows from source to targets
def self.copy(source_tracker, source_role, target_trackers, target_roles)
unless source_tracker.is_a?(Tracker) || source_role.is_a?(Role)
raise ArgumentError.new "source_tracker or source_role must be specified"
end
target_trackers = [target_trackers].flatten.compact
target_roles = [target_roles].flatten.compact
target_trackers = Tracker.all if target_trackers.empty?
target_roles = Role.all if target_roles.empty?
target_trackers.each do |target_tracker|
target_roles.each do |target_role|
copy_one(source_tracker || target_tracker,
source_role || target_role,
target_tracker,
target_role)
end
end
end
# Copies a single set of workflows from source to target
def self.copy_one(source_tracker, source_role, target_tracker, target_role)
unless source_tracker.is_a?(Tracker) && !source_tracker.new_record? &&
source_role.is_a?(Role) && !source_role.new_record? &&
target_tracker.is_a?(Tracker) && !target_tracker.new_record? &&
target_role.is_a?(Role) && !target_role.new_record?
raise ArgumentError.new("arguments can not be nil or unsaved objects")
end
if source_tracker == target_tracker && source_role == target_role
false
else
transaction do
delete_all :tracker_id => target_tracker.id, :role_id => target_role.id
connection.insert "INSERT INTO #{Workflow.table_name} (tracker_id, role_id, old_status_id, new_status_id)" +
" SELECT #{target_tracker.id}, #{target_role.id}, old_status_id, new_status_id" +
" FROM #{Workflow.table_name}" +
" WHERE tracker_id = #{source_tracker.id} AND role_id = #{source_role.id}"
end
true
end
end
end
+5
View File
@@ -0,0 +1,5 @@
<div class="contextual">
<%= link_to l(:button_edit), {:action => 'edit'}, :class => 'icon icon-edit' %>
<%= link_to l(:button_copy), {:action => 'copy'}, :class => 'icon icon-copy' %>
<%= link_to l(:field_summary), {:action => 'index'}, :class => 'icon icon-summary' %>
</div>
+33
View File
@@ -0,0 +1,33 @@
<%= render :partial => 'action_menu' %>
<h2><%=l(:label_workflow)%></h2>
<% form_tag({}, :id => 'workflow_copy_form') do %>
<div class="tabular box">
<p>
<label><%= l(:label_copy_source) %></label>
<%= l(:label_tracker) %><br />
<%= select_tag('source_tracker_id',
"<option value=\"\">--- #{l(:actionview_instancetag_blank_option)} ---</option>" +
"<option value=\"any\">--- #{ l(:label_copy_same_as_target) } ---</option>" +
options_from_collection_for_select(@trackers, 'id', 'name', @source_tracker && @source_tracker.id)) %><br />
<%= l(:label_role) %><br />
<%= select_tag('source_role_id',
"<option value=\"\">--- #{l(:actionview_instancetag_blank_option)} ---</option>" +
"<option value=\"any\">--- #{ l(:label_copy_same_as_target) } ---</option>" +
options_from_collection_for_select(@roles, 'id', 'name', @source_role && @source_role.id)) %>
</p>
<p>
<label><%= l(:label_copy_target) %></label>
<%= l(:label_tracker) %><br />
<%= select_tag 'target_tracker_ids',
"<option value=\"\" disabled=\"disabled\">--- #{l(:actionview_instancetag_blank_option)} ---</option>" +
options_from_collection_for_select(@trackers, 'id', 'name', @target_trackers && @target_trackers.map(&:id)), :multiple => true %><br />
<%= l(:label_role) %><br />
<%= select_tag 'target_role_ids',
"<option value=\"\" disabled=\"disabled\">--- #{l(:actionview_instancetag_blank_option)} ---</option>" +
options_from_collection_for_select(@roles, 'id', 'name', @target_roles && @target_roles.map(&:id)), :multiple => true %>
</p>
</div>
<%= submit_tag l(:button_copy) %>
<% end %>
+1 -3
View File
@@ -1,6 +1,4 @@
<div class="contextual">
<%= link_to l(:field_summary), :action => 'index' %>
</div>
<%= render :partial => 'action_menu' %>
<h2><%=l(:label_workflow)%></h2>
+2
View File
@@ -1,3 +1,5 @@
<%= render :partial => 'action_menu' %>
<h2><%=l(:label_workflow)%></h2>
<% if @workflow_counts.empty? %>