Copy issues via bulk update action.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@8538 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
1 parent
464cef8643
commit
065376c160
13 files changed
+99
-327
No files matched your search
@@ -1,85 +0,0 @@
|
||||
# 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
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class IssueMovesController < ApplicationController
|
||||
menu_item :issues
|
||||
|
||||
default_search_scope :issues
|
||||
before_filter :find_issues, :check_project_uniqueness
|
||||
before_filter :authorize
|
||||
|
||||
def new
|
||||
prepare_for_issue_move
|
||||
render :layout => false if request.xhr?
|
||||
end
|
||||
|
||||
def create
|
||||
prepare_for_issue_move
|
||||
|
||||
if request.post?
|
||||
new_tracker = params[:new_tracker_id].blank? ? nil : @target_project.trackers.find_by_id(params[:new_tracker_id])
|
||||
unsaved_issue_ids = []
|
||||
moved_issues = []
|
||||
@issues.each do |issue|
|
||||
issue.reload
|
||||
call_hook(:controller_issues_move_before_save, { :params => params, :issue => issue, :target_project => @target_project, :copy => !!@copy })
|
||||
if r = issue.move_to_project(@target_project, new_tracker, {:copy => @copy, :attributes => extract_changed_attributes_for_move(params), :notes => @notes})
|
||||
moved_issues << r
|
||||
else
|
||||
unsaved_issue_ids << issue.id
|
||||
end
|
||||
end
|
||||
set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
|
||||
|
||||
if params[:follow]
|
||||
if @issues.size == 1 && moved_issues.size == 1
|
||||
redirect_to :controller => 'issues', :action => 'show', :id => moved_issues.first
|
||||
else
|
||||
redirect_to :controller => 'issues', :action => 'index', :project_id => (@target_project || @project)
|
||||
end
|
||||
else
|
||||
redirect_to :controller => 'issues', :action => 'index', :project_id => @project
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def prepare_for_issue_move
|
||||
@issues.sort!
|
||||
@copy = params[:copy_options] && params[:copy_options][:copy]
|
||||
@allowed_projects = Issue.allowed_target_projects_on_move
|
||||
@target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id]
|
||||
@target_project ||= @project
|
||||
@trackers = @target_project.trackers
|
||||
@available_statuses = Workflow.available_statuses(@project)
|
||||
@notes = params[:notes]
|
||||
@notes ||= ''
|
||||
end
|
||||
|
||||
def extract_changed_attributes_for_move(params)
|
||||
changed_attributes = {}
|
||||
[:assigned_to_id, :status_id, :start_date, :due_date, :priority_id].each do |valid_attribute|
|
||||
unless params[valid_attribute].blank?
|
||||
changed_attributes[valid_attribute] = (params[valid_attribute] == 'none' ? nil : params[valid_attribute])
|
||||
end
|
||||
end
|
||||
changed_attributes
|
||||
end
|
||||
|
||||
end
|
||||
@@ -206,9 +206,11 @@ class IssuesController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# Bulk edit a set of issues
|
||||
# Bulk edit/copy a set of issues
|
||||
def bulk_edit
|
||||
@issues.sort!
|
||||
@copy = params[:copy].present?
|
||||
@notes = params[:notes]
|
||||
|
||||
if User.current.allowed_to?(:move_issues, @projects)
|
||||
@allowed_projects = Issue.allowed_target_projects_on_move
|
||||
@@ -226,18 +228,21 @@ class IssuesController < ApplicationController
|
||||
@assignables = target_projects.map(&:assignable_users).inject{|memo,a| memo & a}
|
||||
@trackers = target_projects.map(&:trackers).inject{|memo,t| memo & t}
|
||||
|
||||
@notes = params[:notes]
|
||||
render :layout => false if request.xhr?
|
||||
end
|
||||
|
||||
def bulk_update
|
||||
@issues.sort!
|
||||
@copy = params[:copy].present?
|
||||
attributes = parse_params_for_bulk_issue_attributes(params)
|
||||
|
||||
unsaved_issue_ids = []
|
||||
moved_issues = []
|
||||
@issues.each do |issue|
|
||||
issue.reload
|
||||
if @copy
|
||||
issue = Issue.new.copy_from(issue)
|
||||
end
|
||||
journal = issue.init_journal(User.current, params[:notes])
|
||||
issue.safe_attributes = attributes
|
||||
call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# encoding: utf-8
|
||||
#
|
||||
module IssueMovesHelper
|
||||
end
|
||||
@@ -110,7 +110,7 @@
|
||||
<li><%= context_menu_link l(:button_duplicate), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue},
|
||||
:class => 'icon-duplicate', :disabled => !@can[:copy] %></li>
|
||||
<% end %>
|
||||
<li><%= context_menu_link l(:button_copy), new_issue_move_path(:ids => @issues.collect(&:id), :copy_options => {:copy => 't'}),
|
||||
<li><%= context_menu_link l(:button_copy), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :copy => '1'},
|
||||
:class => 'icon-copy', :disabled => !@can[:move] %></li>
|
||||
<li><%= context_menu_link l(:button_delete), issues_path(:ids => @issues.collect(&:id), :back_url => @back),
|
||||
:method => :delete, :confirm => issues_destroy_confirmation_message(@issues), :class => 'icon-del', :disabled => !@can[:delete] %></li>
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
<h2><%= @copy ? l(:button_copy) : l(:button_move) %></h2>
|
||||
|
||||
<ul>
|
||||
<% @issues.each do |issue| -%>
|
||||
<li><%= link_to_issue issue %></li>
|
||||
<% end -%>
|
||||
</ul>
|
||||
|
||||
<% form_tag({:action => 'create'}, :id => 'move_form') do %>
|
||||
<%= @issues.collect {|i| hidden_field_tag('ids[]', i.id)}.join("\n").html_safe %>
|
||||
|
||||
<div class="box tabular">
|
||||
<fieldset class="attributes">
|
||||
<legend><%= l(:label_change_properties) %></legend>
|
||||
|
||||
<div class="splitcontentleft">
|
||||
<p><label for="new_project_id"><%=l(:field_project)%>:</label>
|
||||
<%= select_tag "new_project_id",
|
||||
project_tree_options_for_select(@allowed_projects, :selected => @target_project),
|
||||
:onchange => remote_function(:url => { :action => 'new' },
|
||||
:method => :get,
|
||||
:update => 'content',
|
||||
:with => "Form.serialize('move_form')") %></p>
|
||||
|
||||
<p><label for="new_tracker_id"><%=l(:field_tracker)%>:</label>
|
||||
<%= select_tag "new_tracker_id", "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@trackers, "id", "name") %></p>
|
||||
|
||||
<p>
|
||||
<label for='status_id'><%= l(:field_status) %></label>
|
||||
<%= select_tag('status_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@available_statuses, :id, :name)) %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for='priority_id'><%= l(:field_priority) %></label>
|
||||
<%= select_tag('priority_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(IssuePriority.active, :id, :name)) %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for='assigned_to_id'><%= l(:field_assigned_to) %></label>
|
||||
<%= select_tag('assigned_to_id', content_tag('option', l(:label_no_change_option), :value => '') +
|
||||
content_tag('option', l(:label_nobody), :value => 'none') +
|
||||
principals_options_for_select(@target_project.assignable_users)) %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="splitcontentright">
|
||||
<p>
|
||||
<label for='start_date'><%= l(:field_start_date) %></label>
|
||||
<%= text_field_tag 'start_date', '', :size => 10 %><%= calendar_for('start_date') %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for='due_date'><%= l(:field_due_date) %></label>
|
||||
<%= text_field_tag 'due_date', '', :size => 10 %><%= calendar_for('due_date') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset><legend><%= l(:field_notes) %></legend>
|
||||
<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %>
|
||||
<%= wikitoolbar_for 'notes' %>
|
||||
</fieldset>
|
||||
|
||||
<%= call_hook(:view_issues_move_bottom, :issues => @issues, :target_project => @target_project, :copy => !!@copy) %>
|
||||
</div>
|
||||
|
||||
<% if @copy %>
|
||||
<%= hidden_field_tag("copy_options[copy]", "1") %>
|
||||
<%= submit_tag l(:button_copy) %>
|
||||
<%= submit_tag l(:button_copy_and_follow), :name => 'follow' %>
|
||||
<% else %>
|
||||
<%= submit_tag l(:button_move) %>
|
||||
<%= submit_tag l(:button_move_and_follow), :name => 'follow' %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% content_for :header_tags do %>
|
||||
<%= robot_exclusion_tag %>
|
||||
<% end %>
|
||||
@@ -3,6 +3,6 @@
|
||||
<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'new', :issue_id => @issue}, :class => 'icon icon-time-add' %>
|
||||
<%= watcher_tag(@issue, User.current) %>
|
||||
<%= link_to_if_authorized l(:button_duplicate), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue }, :class => 'icon icon-duplicate' %>
|
||||
<%= link_to_if_authorized l(:button_copy), {:controller => 'issue_moves', :action => 'new', :id => @issue, :copy_options => {:copy => 't'}}, :class => 'icon icon-copy' %>
|
||||
<%= link_to_if_authorized l(:button_copy), {:controller => 'issues', :action => 'bulk_edit', :id => @issue, :copy => '1'}, :class => 'icon icon-copy' %>
|
||||
<%= link_to l(:button_delete), issue_path(@issue), :confirm => issues_destroy_confirmation_message(@issue), :method => :delete, :class => 'icon icon-del' if User.current.allowed_to?(:delete_issues, @project) %>
|
||||
</div>
|
||||
@@ -1,4 +1,4 @@
|
||||
<h2><%= l(:label_bulk_edit_selected_issues) %></h2>
|
||||
<h2><%= @copy ? l(:button_copy) : l(:label_bulk_edit_selected_issues) %></h2>
|
||||
|
||||
<ul><%= @issues.collect {|i|
|
||||
content_tag('li',
|
||||
@@ -102,7 +102,11 @@
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<% if @target_project %>
|
||||
<% if @copy %>
|
||||
<%= hidden_field_tag 'copy', '1' %>
|
||||
<%= submit_tag l(:button_copy) %>
|
||||
<%= submit_tag l(:button_copy_and_follow), :name => 'follow' %>
|
||||
<% elsif @target_project %>
|
||||
<%= submit_tag l(:button_move) %>
|
||||
<%= submit_tag l(:button_move_and_follow), :name => 'follow' %>
|
||||
<% else %>
|
||||
|
||||
Reference in new issue
Block a user