##// END OF EJS Templates
Make Tracker map-able for CSV import (#22951)....
Jean-Philippe Lang -
r15108:e3875ffd5739
parent child
Show More
@@ -57,11 +57,7 class ImportsController < ApplicationController
57 end
57 end
58
58
59 def mapping
59 def mapping
60 issue = Issue.new
60 @custom_fields = @import.mappable_custom_fields
61 issue.project = @import.project
62 issue.tracker = @import.tracker
63 @attributes = issue.safe_attribute_names
64 @custom_fields = issue.editable_custom_field_values.map(&:custom_field)
65
61
66 if request.post?
62 if request.post?
67 respond_to do |format|
63 respond_to do |format|
@@ -23,12 +23,16 module ImportsHelper
23 blank_text = options[:required] ? "-- #{l(:actionview_instancetag_blank_option)} --" : "&nbsp;".html_safe
23 blank_text = options[:required] ? "-- #{l(:actionview_instancetag_blank_option)} --" : "&nbsp;".html_safe
24 tags << content_tag('option', blank_text, :value => '')
24 tags << content_tag('option', blank_text, :value => '')
25 tags << options_for_select(import.columns_options, import.mapping[field])
25 tags << options_for_select(import.columns_options, import.mapping[field])
26 if values = options[:values]
27 tags << content_tag('option', '--', :disabled => true)
28 tags << options_for_select(values.map {|text, value| [text, "value:#{value}"]}, import.mapping[field])
29 end
26 tags
30 tags
27 end
31 end
28
32
29 def mapping_select_tag(import, field, options={})
33 def mapping_select_tag(import, field, options={})
30 name = "import_settings[mapping][#{field}]"
34 name = "import_settings[mapping][#{field}]"
31 select_tag name, options_for_mapping_select(import, field, options)
35 select_tag name, options_for_mapping_select(import, field, options), :id => "import_mapping_#{field}"
32 end
36 end
33
37
34 # Returns the options for the date_format setting
38 # Returns the options for the date_format setting
@@ -41,8 +41,10 class IssueImport < Import
41 end
41 end
42
42
43 def tracker
43 def tracker
44 tracker_id = mapping['tracker_id'].to_i
44 if mapping['tracker'].to_s =~ /\Avalue:(\d+)\z/
45 allowed_target_trackers.find_by_id(tracker_id) || allowed_target_trackers.first
45 tracker_id = $1.to_i
46 allowed_target_trackers.find_by_id(tracker_id)
47 end
46 end
48 end
47
49
48 # Returns true if missing categories should be created during the import
50 # Returns true if missing categories should be created during the import
@@ -57,6 +59,19 class IssueImport < Import
57 mapping['create_versions'] == '1'
59 mapping['create_versions'] == '1'
58 end
60 end
59
61
62 def mappable_custom_fields
63 if tracker
64 issue = Issue.new
65 issue.project = project
66 issue.tracker = tracker
67 issue.editable_custom_field_values(user).map(&:custom_field)
68 elsif project
69 project.all_issue_custom_fields
70 else
71 []
72 end
73 end
74
60 private
75 private
61
76
62 def build_object(row)
77 def build_object(row)
@@ -64,12 +79,20 class IssueImport < Import
64 issue.author = user
79 issue.author = user
65 issue.notify = false
80 issue.notify = false
66
81
82 tracker_id = nil
83 if tracker
84 tracker_id = tracker.id
85 elsif tracker_name = row_value(row, 'tracker')
86 tracker_id = allowed_target_trackers.named(tracker_name).first.try(:id)
87 end
88
67 attributes = {
89 attributes = {
68 'project_id' => mapping['project_id'],
90 'project_id' => mapping['project_id'],
69 'tracker_id' => mapping['tracker_id'],
91 'tracker_id' => tracker_id,
70 'subject' => row_value(row, 'subject'),
92 'subject' => row_value(row, 'subject'),
71 'description' => row_value(row, 'description')
93 'description' => row_value(row, 'description')
72 }
94 }
95 attributes
73 issue.send :safe_attributes=, attributes, user
96 issue.send :safe_attributes=, attributes, user
74
97
75 attributes = {}
98 attributes = {}
@@ -149,6 +172,11 class IssueImport < Import
149 end
172 end
150
173
151 issue.send :safe_attributes=, attributes, user
174 issue.send :safe_attributes=, attributes, user
175
176 if issue.tracker_id != tracker_id
177 issue.tracker_id = nil
178 end
179
152 issue
180 issue
153 end
181 end
154 end
182 end
@@ -1,17 +1,17
1 <div class="splitcontent">
2 <div class="splitcontentleft">
3 <p>
1 <p>
4 <label><%= l(:label_project) %></label>
2 <label><%= l(:label_project) %></label>
5 <%= select_tag 'import_settings[mapping][project_id]',
3 <%= select_tag 'import_settings[mapping][project_id]',
6 options_for_select(project_tree_options_for_select(@import.allowed_target_projects, :selected => @import.project)),
4 options_for_select(project_tree_options_for_select(@import.allowed_target_projects, :selected => @import.project)),
7 :id => 'issue_project_id' %>
5 :id => 'import_mapping_project_id' %>
8 </p>
6 </p>
9 <p>
7 <p>
10 <label><%= l(:label_tracker) %></label>
8 <label><%= l(:label_tracker) %></label>
11 <%= select_tag 'import_settings[mapping][tracker_id]',
9 <%= mapping_select_tag @import, 'tracker', :required => true,
12 options_for_select(@import.allowed_target_trackers.sorted.map {|t| [t.name, t.id]}, @import.tracker.try(:id)),
10 :values => @import.allowed_target_trackers.sorted.map {|t| [t.name, t.id]} %>
13 :id => 'issue_tracker_id' %>
14 </p>
11 </p>
12
13 <div class="splitcontent">
14 <div class="splitcontentleft">
15 <p>
15 <p>
16 <label><%= l(:field_subject) %></label>
16 <label><%= l(:field_subject) %></label>
17 <%= mapping_select_tag @import, 'subject', :required => true %>
17 <%= mapping_select_tag @import, 'subject', :required => true %>
@@ -35,7 +35,7
35
35
36 <%= javascript_tag do %>
36 <%= javascript_tag do %>
37 $(document).ready(function() {
37 $(document).ready(function() {
38 $('#fields-mapping').on('change', '#issue_project_id, #issue_tracker_id', function(){
38 $('#fields-mapping').on('change', '#import_mapping_project_id, #import_mapping_tracker', function(){
39 $.ajax({
39 $.ajax({
40 url: '<%= import_mapping_path(@import, :format => 'js') %>',
40 url: '<%= import_mapping_path(@import, :format => 'js') %>',
41 type: 'post',
41 type: 'post',
@@ -1,4 +1,4
1 priority;subject;description;start_date;due_date;parent;private;progress;custom;version;category;user;estimated_hours
1 priority;subject;description;start_date;due_date;parent;private;progress;custom;version;category;user;estimated_hours;tracker
2 High;First;First description;2015-07-08;2015-08-25;;no;;PostgreSQL;;New category;dlopper;1
2 High;First;First description;2015-07-08;2015-08-25;;no;;PostgreSQL;;New category;dlopper;1;bug
3 Normal;Child 1;Child description;;;1;yes;10;MySQL;2.0;New category;;2
3 Normal;Child 1;Child description;;;1;yes;10;MySQL;2.0;New category;;2;feature request
4 Normal;Child of existing issue;Child description;;;#2;no;20;;2.1;Printing;;3
4 Normal;Child of existing issue;Child description;;;#2;no;20;;2.1;Printing;;3;bug
@@ -235,7 +235,7 module ObjectHelpers
235
235
236 import.settings = {
236 import.settings = {
237 'separator' => ";", 'wrapper' => '"', 'encoding' => "UTF-8",
237 'separator' => ";", 'wrapper' => '"', 'encoding' => "UTF-8",
238 'mapping' => {'project_id' => '1', 'tracker_id' => '2', 'subject' => '1'}
238 'mapping' => {'project_id' => '1', 'tracker' => '13', 'subject' => '1'}
239 }
239 }
240 import.save!
240 import.save!
241 import
241 import
@@ -58,6 +58,37 class IssueImportTest < ActiveSupport::TestCase
58 assert_equal 'New category', category.name
58 assert_equal 'New category', category.name
59 end
59 end
60
60
61 def test_mapping_with_fixed_tracker
62 import = generate_import_with_mapping
63 import.mapping.merge!('tracker' => 'value:2')
64 import.save!
65
66 issues = new_records(Issue, 3) { import.run }
67 assert_equal [2], issues.map(&:tracker_id).uniq
68 end
69
70 def test_mapping_with_mapped_tracker
71 import = generate_import_with_mapping
72 import.mapping.merge!('tracker' => '13')
73 import.save!
74
75 issues = new_records(Issue, 3) { import.run }
76 assert_equal [1, 2, 1], issues.map(&:tracker_id)
77 end
78
79 def test_should_not_import_with_default_tracker_when_tracker_is_invalid
80 Tracker.find_by_name('Feature request').update!(:name => 'Feature')
81
82 import = generate_import_with_mapping
83 import.mapping.merge!('tracker' => '13')
84 import.save!
85 import.run
86
87 assert_equal 1, import.unsaved_items.count
88 item = import.unsaved_items.first
89 assert_include "Tracker cannot be blank", item.message
90 end
91
61 def test_parent_should_be_set
92 def test_parent_should_be_set
62 import = generate_import_with_mapping
93 import = generate_import_with_mapping
63 import.mapping.merge!('parent_issue_id' => '5')
94 import.mapping.merge!('parent_issue_id' => '5')
@@ -101,7 +132,7 class IssueImportTest < ActiveSupport::TestCase
101 field = IssueCustomField.generate!(:field_format => 'date', :is_for_all => true, :trackers => Tracker.all)
132 field = IssueCustomField.generate!(:field_format => 'date', :is_for_all => true, :trackers => Tracker.all)
102 import = generate_import_with_mapping('import_dates.csv')
133 import = generate_import_with_mapping('import_dates.csv')
103 import.settings.merge!('date_format' => Import::DATE_FORMATS[1])
134 import.settings.merge!('date_format' => Import::DATE_FORMATS[1])
104 import.mapping.merge!('subject' => '0', 'start_date' => '1', 'due_date' => '2', "cf_#{field.id}" => '3')
135 import.mapping.merge!('tracker' => 'value:1', 'subject' => '0', 'start_date' => '1', 'due_date' => '2', "cf_#{field.id}" => '3')
105 import.save!
136 import.save!
106
137
107 issue = new_record(Issue) { import.run } # only 1 valid issue
138 issue = new_record(Issue) { import.run } # only 1 valid issue
General Comments 0
You need to be logged in to leave comments. Login now