diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2009-12-12 10:06:07 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2009-12-12 10:06:07 +0000 |
commit | 5c6ce51ec9f1f3f6687db06d0faeb61d1524198d (patch) | |
tree | 34b9083d62a6f99dbc297837f7f93ea11e0cf813 /app | |
parent | ddeaf9da965c1145e65c1552414b3432a5291ea1 (diff) | |
download | redmine-5c6ce51ec9f1f3f6687db06d0faeb61d1524198d.tar.gz redmine-5c6ce51ec9f1f3f6687db06d0faeb61d1524198d.zip |
Adds workflow copy functionality (#1727).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3154 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/workflows_controller.rb | 23 | ||||
-rw-r--r-- | app/models/role.rb | 10 | ||||
-rw-r--r-- | app/models/tracker.rb | 10 | ||||
-rw-r--r-- | app/models/workflow.rb | 46 | ||||
-rw-r--r-- | app/views/workflows/_action_menu.rhtml | 5 | ||||
-rw-r--r-- | app/views/workflows/copy.rhtml | 33 | ||||
-rw-r--r-- | app/views/workflows/edit.rhtml | 4 | ||||
-rw-r--r-- | app/views/workflows/index.rhtml | 2 |
8 files changed, 114 insertions, 19 deletions
diff --git a/app/controllers/workflows_controller.rb b/app/controllers/workflows_controller.rb index 380d4e752..f11aa4730 100644 --- a/app/controllers/workflows_controller.rb +++ b/app/controllers/workflows_controller.rb @@ -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 diff --git a/app/models/role.rb b/app/models/role.rb index db5825702..22ce2a650 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -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 diff --git a/app/models/tracker.rb b/app/models/tracker.rb index 7c5bae250..8f7a98c39 100644 --- a/app/models/tracker.rb +++ b/app/models/tracker.rb @@ -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 diff --git a/app/models/workflow.rb b/app/models/workflow.rb index a96abaf18..da358b518 100644 --- a/app/models/workflow.rb +++ b/app/models/workflow.rb @@ -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 diff --git a/app/views/workflows/_action_menu.rhtml b/app/views/workflows/_action_menu.rhtml new file mode 100644 index 000000000..577281128 --- /dev/null +++ b/app/views/workflows/_action_menu.rhtml @@ -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> diff --git a/app/views/workflows/copy.rhtml b/app/views/workflows/copy.rhtml new file mode 100644 index 000000000..2cecc8411 --- /dev/null +++ b/app/views/workflows/copy.rhtml @@ -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 %> diff --git a/app/views/workflows/edit.rhtml b/app/views/workflows/edit.rhtml index 399825de2..4feaf3a7c 100644 --- a/app/views/workflows/edit.rhtml +++ b/app/views/workflows/edit.rhtml @@ -1,6 +1,4 @@ -<div class="contextual"> -<%= link_to l(:field_summary), :action => 'index' %> -</div> +<%= render :partial => 'action_menu' %> <h2><%=l(:label_workflow)%></h2> diff --git a/app/views/workflows/index.rhtml b/app/views/workflows/index.rhtml index 2fd080d8f..9f06269b6 100644 --- a/app/views/workflows/index.rhtml +++ b/app/views/workflows/index.rhtml @@ -1,3 +1,5 @@ +<%= render :partial => 'action_menu' %> + <h2><%=l(:label_workflow)%></h2> <% if @workflow_counts.empty? %> |