Browse Source

Bulk addition of related issues (#33418).

Patch by Dmitry Makurin and Marius BALTEANU.


git-svn-id: http://svn.redmine.org/redmine/trunk@20689 e93f8b46-1217-0410-a6f0-8f06a7374b81
tags/4.2.0
Go MAEDA 3 years ago
parent
commit
30e80d82ce

+ 24
- 9
app/controllers/issue_relations_controller.rb View File

@@ -44,22 +44,29 @@ class IssueRelationsController < ApplicationController
end

def create
@relation = IssueRelation.new
@relation.issue_from = @issue
@relation.safe_attributes = params[:relation]
@relation.init_journals(User.current)
saved = false
params_relation = params[:relation]
unsaved_relations = []

relation_issues_to_id.each do |issue_to_id|
params_relation[:issue_to_id] = issue_to_id

@relation = IssueRelation.new
@relation.issue_from = @issue
@relation.safe_attributes = params_relation
@relation.init_journals(User.current)

begin
saved = @relation.save
rescue ActiveRecord::RecordNotUnique
saved = false
@relation.errors.add :base, :taken
unless saved = @relation.save
saved = false
unsaved_relations << @relation
end
end

respond_to do |format|
format.html {redirect_to issue_path(@issue)}
format.js do
@relations = @issue.reload.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible?}
@unsaved_relations = unsaved_relations
end
format.api do
if saved
@@ -98,4 +105,12 @@ class IssueRelationsController < ApplicationController
rescue ActiveRecord::RecordNotFound
render_404
end

def relation_issues_to_id
params[:relation].require(:issue_to_id).split(',').reject(&:blank?)
rescue ActionController::ParameterMissing => e
# We return a empty array just to loop once and return a validation error
# ToDo: Find a better method to return an error if the param is missing.
['']
end
end

+ 19
- 0
app/helpers/issue_relations_helper.rb View File

@@ -22,4 +22,23 @@ module IssueRelationsHelper
values = IssueRelation::TYPES
values.keys.sort_by{|k| values[k][:order]}.collect{|k| [l(values[k][:name]), k]}
end

def relation_error_messages(relations)
messages = {}
relations.each do |item|
item.errors.full_messages.each do |message|
messages[message] ||= []
messages[message] << item
end
end

messages.map do |message, items|
ids = items.map(&:issue_to_id).compact
if ids.empty?
message
else
"#{message}: ##{ids.join(', ')}"
end
end
end
end

+ 12
- 3
app/views/issue_relations/_form.html.erb View File

@@ -1,7 +1,16 @@
<%= error_messages_for 'relation' %>

<% unsaved_relations_ids = '' %>
<% if @unsaved_relations && @unsaved_relations.any? %>
<% unsaved_relations_ids = @unsaved_relations.map(&:issue_to_id).compact.join(", ") %>
<div id="errorExplanation">
<ul>
<% relation_error_messages(@unsaved_relations).each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p><%= f.select :relation_type, collection_for_relation_type_select, {}, :onchange => "setPredecessorFieldsVisibility();" %>
<%= l(:label_issue) %> #<%= f.text_field :issue_to_id, :size => 10 %>
<%= l(:label_issue) %> #<%= f.text_field :issue_to_id, :value => unsaved_relations_ids, :size => 10 %>
<span id="predecessor_fields" style="display:none;">
<%= l(:field_delay) %>: <%= f.text_field :delay, :size => 3 %> <%= l(:label_day_plural) %>
</span>

+ 47
- 0
test/functional/issue_relations_controller_test.rb View File

@@ -216,6 +216,53 @@ class IssueRelationsControllerTest < Redmine::ControllerTest
assert_include 'Related issue cannot be blank', response.body
end

def test_bulk_create_with_multiple_issue_to_id_issues
assert_difference 'IssueRelation.count', +3 do
post :create, :params => {
:issue_id => 1,
:relation => {
# js autocomplete adds a comma at the end
# issue to id should accept both id and hash with id
:issue_to_id => '2,3,#7, ',
:relation_type => 'relates',
:delay => ''
}
},
:xhr => true
end

assert_response :success
relations = IssueRelation.where(:issue_from_id => 1, :issue_to_id => [2, 3, 7])
assert_equal 3, relations.count
# all relations types should be 'relates'
relations.map {|r| assert_equal 'relates', r.relation_type}

# no error messages should be returned in the response
assert_not_include 'id=\"errorExplanation\"', response.body
end

def test_bulk_create_should_show_errors
assert_difference 'IssueRelation.count', +3 do
post :create, :params => {
:issue_id => 1,
:relation => {
:issue_to_id => '1,2,3,4,5,7',
:relation_type => 'relates',
:delay => ''
}
},
:xhr => true
end

assert_response :success
assert_equal 'text/javascript', response.media_type
# issue #1 is invalid
assert_include 'Related issue is invalid: #1', response.body
# issues #4 and #5 can't be related by default
assert_include 'Related issue cannot be blank', response.body
assert_include 'Related issue doesn&#39;t belong to the same project', response.body
end

def test_destroy
assert_difference 'IssueRelation.count', -1 do
delete(:destroy, :params => {:id => '2'})

Loading…
Cancel
Save