end
def mapping
- issue = Issue.new
- issue.project = @import.project
- issue.tracker = @import.tracker
- @attributes = issue.safe_attribute_names
- @custom_fields = issue.editable_custom_field_values.map(&:custom_field)
+ @custom_fields = @import.mappable_custom_fields
if request.post?
respond_to do |format|
blank_text = options[:required] ? "-- #{l(:actionview_instancetag_blank_option)} --" : " ".html_safe
tags << content_tag('option', blank_text, :value => '')
tags << options_for_select(import.columns_options, import.mapping[field])
+ if values = options[:values]
+ tags << content_tag('option', '--', :disabled => true)
+ tags << options_for_select(values.map {|text, value| [text, "value:#{value}"]}, import.mapping[field])
+ end
tags
end
def mapping_select_tag(import, field, options={})
name = "import_settings[mapping][#{field}]"
- select_tag name, options_for_mapping_select(import, field, options)
+ select_tag name, options_for_mapping_select(import, field, options), :id => "import_mapping_#{field}"
end
# Returns the options for the date_format setting
# Checks that the issue can not be added/moved to a disabled tracker
if project && (tracker_id_changed? || project_id_changed?)
- unless project.trackers.include?(tracker)
+ if tracker && !project.trackers.include?(tracker)
errors.add :tracker_id, :inclusion
end
end
end
def tracker
- tracker_id = mapping['tracker_id'].to_i
- allowed_target_trackers.find_by_id(tracker_id) || allowed_target_trackers.first
+ if mapping['tracker'].to_s =~ /\Avalue:(\d+)\z/
+ tracker_id = $1.to_i
+ allowed_target_trackers.find_by_id(tracker_id)
+ end
end
# Returns true if missing categories should be created during the import
mapping['create_versions'] == '1'
end
+ def mappable_custom_fields
+ if tracker
+ issue = Issue.new
+ issue.project = project
+ issue.tracker = tracker
+ issue.editable_custom_field_values(user).map(&:custom_field)
+ elsif project
+ project.all_issue_custom_fields
+ else
+ []
+ end
+ end
+
private
def build_object(row)
issue.author = user
issue.notify = false
+ tracker_id = nil
+ if tracker
+ tracker_id = tracker.id
+ elsif tracker_name = row_value(row, 'tracker')
+ tracker_id = allowed_target_trackers.named(tracker_name).first.try(:id)
+ end
+
attributes = {
'project_id' => mapping['project_id'],
- 'tracker_id' => mapping['tracker_id'],
+ 'tracker_id' => tracker_id,
'subject' => row_value(row, 'subject'),
'description' => row_value(row, 'description')
}
+ if status_name = row_value(row, 'status')
+ if status_id = IssueStatus.named(status_name).first.try(:id)
+ attributes['status_id'] = status_id
+ end
+ end
issue.send :safe_attributes=, attributes, user
attributes = {}
end
issue.send :safe_attributes=, attributes, user
+
+ if issue.tracker_id != tracker_id
+ issue.tracker_id = nil
+ end
+
issue
end
end
-<div class="splitcontent">
-<div class="splitcontentleft">
<p>
<label><%= l(:label_project) %></label>
<%= select_tag 'import_settings[mapping][project_id]',
options_for_select(project_tree_options_for_select(@import.allowed_target_projects, :selected => @import.project)),
- :id => 'issue_project_id' %>
+ :id => 'import_mapping_project_id' %>
</p>
<p>
<label><%= l(:label_tracker) %></label>
- <%= select_tag 'import_settings[mapping][tracker_id]',
- options_for_select(@import.allowed_target_trackers.sorted.map {|t| [t.name, t.id]}, @import.tracker.try(:id)),
- :id => 'issue_tracker_id' %>
+ <%= mapping_select_tag @import, 'tracker', :required => true,
+ :values => @import.allowed_target_trackers.sorted.map {|t| [t.name, t.id]} %>
+</p>
+<p>
+ <label><%= l(:field_status) %></label>
+ <%= mapping_select_tag @import, 'status' %>
</p>
+
+<div class="splitcontent">
+<div class="splitcontentleft">
<p>
<label><%= l(:field_subject) %></label>
<%= mapping_select_tag @import, 'subject', :required => true %>
<%= javascript_tag do %>
$(document).ready(function() {
- $('#fields-mapping').on('change', '#issue_project_id, #issue_tracker_id', function(){
+ $('#fields-mapping').on('change', '#import_mapping_project_id, #import_mapping_tracker', function(){
$.ajax({
url: '<%= import_mapping_path(@import, :format => 'js') %>',
type: 'post',
<h2><%= l(:label_import_issues) %></h2>
-<% if @import.unsaved_items.count == 0 %>
+<% if @import.saved_items.count > 0 %>
<p><%= l(:notice_import_finished, :count => @import.saved_items.count) %></p>
- <ul>
+ <ul id="saved-items">
<% @import.saved_objects.each do |issue| %>
<li><%= link_to_issue issue %></li>
<% end %>
</ul>
-<% else %>
+<% end %>
+
+<% if @import.unsaved_items.count > 0 %>
<p><%= l(:notice_import_finished_with_errors, :count => @import.unsaved_items.count, :total => @import.total_items) %></p>
<table id="unsaved-items" class="list">
+ <thead>
<tr>
<th>Position</th>
<th>Message</th>
</tr>
- <% @import.unsaved_items.each do |item| %>
+ </thead>
+ <tbody>
+ <% @import.unsaved_items.each do |item| %>
<tr>
<td><%= item.position %></td>
<td><%= simple_format_without_paragraph item.message %></td>
</tr>
- <% end %>
+ <% end %>
+ </tbody>
</table>
<% end %>
-priority;subject;description;start_date;due_date;parent;private;progress;custom;version;category;user;estimated_hours
-High;First;First description;2015-07-08;2015-08-25;;no;;PostgreSQL;;New category;dlopper;1
-Normal;Child 1;Child description;;;1;yes;10;MySQL;2.0;New category;;2
-Normal;Child of existing issue;Child description;;;#2;no;20;;2.1;Printing;;3
+priority;subject;description;start_date;due_date;parent;private;progress;custom;version;category;user;estimated_hours;tracker;status
+High;First;First description;2015-07-08;2015-08-25;;no;;PostgreSQL;;New category;dlopper;1;bug;new
+Normal;Child 1;Child description;;;1;yes;10;MySQL;2.0;New category;;2;feature request;new
+Normal;Child of existing issue;Child description;;;#2;no;20;;2.1;Printing;;3;bug;assigned
get :show, :id => import.to_param
assert_response :success
assert_template 'show'
+ assert_select 'ul#saved-items'
+ assert_select 'ul#saved-items li', import.saved_items.count
assert_select 'table#unsaved-items', 0
end
assert_response :success
assert_template 'show'
assert_select 'table#unsaved-items'
+ assert_select 'table#unsaved-items tbody tr', import.unsaved_items.count
end
end
import.settings = {
'separator' => ";", 'wrapper' => '"', 'encoding' => "UTF-8",
- 'mapping' => {'project_id' => '1', 'tracker_id' => '2', 'subject' => '1'}
+ 'mapping' => {'project_id' => '1', 'tracker' => '13', 'subject' => '1'}
}
import.save!
import
assert_equal 'New category', category.name
end
+ def test_mapping_with_fixed_tracker
+ import = generate_import_with_mapping
+ import.mapping.merge!('tracker' => 'value:2')
+ import.save!
+
+ issues = new_records(Issue, 3) { import.run }
+ assert_equal [2], issues.map(&:tracker_id).uniq
+ end
+
+ def test_mapping_with_mapped_tracker
+ import = generate_import_with_mapping
+ import.mapping.merge!('tracker' => '13')
+ import.save!
+
+ issues = new_records(Issue, 3) { import.run }
+ assert_equal [1, 2, 1], issues.map(&:tracker_id)
+ end
+
+ def test_should_not_import_with_default_tracker_when_tracker_is_invalid
+ Tracker.find_by_name('Feature request').update!(:name => 'Feature')
+
+ import = generate_import_with_mapping
+ import.mapping.merge!('tracker' => '13')
+ import.save!
+ import.run
+
+ assert_equal 1, import.unsaved_items.count
+ item = import.unsaved_items.first
+ assert_include "Tracker cannot be blank", item.message
+ end
+
+ def test_status_should_be_set
+ import = generate_import_with_mapping
+ import.mapping.merge!('status' => '14')
+ import.save!
+
+ issues = new_records(Issue, 3) { import.run }
+ assert_equal ['New', 'New', 'Assigned'], issues.map(&:status).map(&:name)
+ end
+
def test_parent_should_be_set
import = generate_import_with_mapping
import.mapping.merge!('parent_issue_id' => '5')
field = IssueCustomField.generate!(:field_format => 'date', :is_for_all => true, :trackers => Tracker.all)
import = generate_import_with_mapping('import_dates.csv')
import.settings.merge!('date_format' => Import::DATE_FORMATS[1])
- import.mapping.merge!('subject' => '0', 'start_date' => '1', 'due_date' => '2', "cf_#{field.id}" => '3')
+ import.mapping.merge!('tracker' => 'value:1', 'subject' => '0', 'start_date' => '1', 'due_date' => '2', "cf_#{field.id}" => '3')
import.save!
issue = new_record(Issue) { import.run } # only 1 valid issue