]> source.dussan.org Git - redmine.git/commitdiff
Merged r15490 to r15493, r15496, r15497 (#22951).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 11 Jun 2016 05:25:46 +0000 (05:25 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 11 Jun 2016 05:25:46 +0000 (05:25 +0000)
git-svn-id: http://svn.redmine.org/redmine/branches/3.3-stable@15500 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/imports_controller.rb
app/helpers/imports_helper.rb
app/models/issue.rb
app/models/issue_import.rb
app/views/imports/_fields_mapping.html.erb
app/views/imports/mapping.html.erb
app/views/imports/show.html.erb
test/fixtures/files/import_issues.csv
test/functional/imports_controller_test.rb
test/object_helpers.rb
test/unit/issue_import_test.rb

index 79a5ced4bc5a501b62758eb37ef992970cc89cb2..75d4da93300c0dc43a85d1bf271ee81b84a99880 100644 (file)
@@ -57,11 +57,7 @@ class ImportsController < ApplicationController
   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|
index 2fecfca24cfe3faebc32ce369c0f83c8e24c4467..edbf2d13e06b4a0bd3a8b2ed1e946cba985e6097 100644 (file)
@@ -23,12 +23,16 @@ module ImportsHelper
     blank_text = options[:required] ? "-- #{l(:actionview_instancetag_blank_option)} --" : "&nbsp;".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
index e0b99e4e6bb0fff5e0f9163d90f4abb0a3f2d921..98e348d6af74e3bb478cddbf6984437b67cf8b2c 100644 (file)
@@ -691,7 +691,7 @@ class Issue < ActiveRecord::Base
 
     # 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
index 5b19ac966e163a8ff388cb9780455225334d1085..4ecd4b517b26d26fdaddb82f4ea3073ecbb16fb6 100644 (file)
@@ -41,8 +41,10 @@ class IssueImport < Import
   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
@@ -57,6 +59,19 @@ class IssueImport < 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)
@@ -64,12 +79,24 @@ class IssueImport < Import
     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 = {}
@@ -149,6 +176,11 @@ class IssueImport < Import
     end
 
     issue.send :safe_attributes=, attributes, user
+
+    if issue.tracker_id != tracker_id
+      issue.tracker_id = nil
+    end
+
     issue
   end
 end
index bb6467ecad7c13bbe320a0935c4a7186a40dbbb6..0e1d455fa2dea0da96ce141f711cd5d63ecc17e9 100644 (file)
@@ -1,17 +1,21 @@
-<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 %>
index 283bddb04b89e3bc87708fe7a364133b1f3cb511..2e225d6c218c5326716dde784767d0ee150c5ada 100644 (file)
@@ -35,7 +35,7 @@
 
 <%= 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',
index d9848cdb542a4c0624b86ab84d428891dcd1f895..a50db99fe354e95c5e302d9961e76a8252105403 100644 (file)
@@ -1,27 +1,33 @@
 <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 %>
 
index 918f9fc7ea8ce834f1f7ba69b69eac3324dd3af9..fa9d226650757487631abd9cf3b74ece5d6ff1cf 100644 (file)
@@ -1,4 +1,4 @@
-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
index 9c8dafa34f4a9bf6325f224845e380fe1e70189c..5c41c10d7f86b143e2debfc7a0990d5512a618e5 100644 (file)
@@ -184,6 +184,8 @@ class ImportsControllerTest < ActionController::TestCase
     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
 
@@ -197,5 +199,6 @@ class ImportsControllerTest < ActionController::TestCase
     assert_response :success
     assert_template 'show'
     assert_select 'table#unsaved-items'
+    assert_select 'table#unsaved-items tbody tr', import.unsaved_items.count
   end
 end
index 2b33279611697876851f3486a1bfa3b091570d75..7ea4a619ab2f89b5c6debb2392ec18cd1c12f4fd 100644 (file)
@@ -235,7 +235,7 @@ module ObjectHelpers
 
     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
index 61e1007003e583a3831ef32d0fd17094c5508943..88da82c88784f1428330a0a9fbb192c45574603b 100644 (file)
@@ -58,6 +58,46 @@ class IssueImportTest < ActiveSupport::TestCase
     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')
@@ -101,7 +141,7 @@ class IssueImportTest < ActiveSupport::TestCase
     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