##// END OF EJS Templates
Merged r15490 to r15493, r15496, r15497 (#22951)....
Jean-Philippe Lang -
r15118:8516e1c88dfe
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
@@ -691,7 +691,7 class Issue < ActiveRecord::Base
691
691
692 # Checks that the issue can not be added/moved to a disabled tracker
692 # Checks that the issue can not be added/moved to a disabled tracker
693 if project && (tracker_id_changed? || project_id_changed?)
693 if project && (tracker_id_changed? || project_id_changed?)
694 unless project.trackers.include?(tracker)
694 if tracker && !project.trackers.include?(tracker)
695 errors.add :tracker_id, :inclusion
695 errors.add :tracker_id, :inclusion
696 end
696 end
697 end
697 end
@@ -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,24 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 if status_name = row_value(row, 'status')
96 if status_id = IssueStatus.named(status_name).first.try(:id)
97 attributes['status_id'] = status_id
98 end
99 end
73 issue.send :safe_attributes=, attributes, user
100 issue.send :safe_attributes=, attributes, user
74
101
75 attributes = {}
102 attributes = {}
@@ -149,6 +176,11 class IssueImport < Import
149 end
176 end
150
177
151 issue.send :safe_attributes=, attributes, user
178 issue.send :safe_attributes=, attributes, user
179
180 if issue.tracker_id != tracker_id
181 issue.tracker_id = nil
182 end
183
152 issue
184 issue
153 end
185 end
154 end
186 end
@@ -1,17 +1,21
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' %>
11 </p>
12 <p>
13 <label><%= l(:field_status) %></label>
14 <%= mapping_select_tag @import, 'status' %>
14 </p>
15 </p>
16
17 <div class="splitcontent">
18 <div class="splitcontentleft">
15 <p>
19 <p>
16 <label><%= l(:field_subject) %></label>
20 <label><%= l(:field_subject) %></label>
17 <%= mapping_select_tag @import, 'subject', :required => true %>
21 <%= 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,27 +1,33
1 <h2><%= l(:label_import_issues) %></h2>
1 <h2><%= l(:label_import_issues) %></h2>
2
2
3 <% if @import.unsaved_items.count == 0 %>
3 <% if @import.saved_items.count > 0 %>
4 <p><%= l(:notice_import_finished, :count => @import.saved_items.count) %></p>
4 <p><%= l(:notice_import_finished, :count => @import.saved_items.count) %></p>
5
5
6 <ul>
6 <ul id="saved-items">
7 <% @import.saved_objects.each do |issue| %>
7 <% @import.saved_objects.each do |issue| %>
8 <li><%= link_to_issue issue %></li>
8 <li><%= link_to_issue issue %></li>
9 <% end %>
9 <% end %>
10 </ul>
10 </ul>
11 <% else %>
11 <% end %>
12
13 <% if @import.unsaved_items.count > 0 %>
12 <p><%= l(:notice_import_finished_with_errors, :count => @import.unsaved_items.count, :total => @import.total_items) %></p>
14 <p><%= l(:notice_import_finished_with_errors, :count => @import.unsaved_items.count, :total => @import.total_items) %></p>
13
15
14 <table id="unsaved-items" class="list">
16 <table id="unsaved-items" class="list">
17 <thead>
15 <tr>
18 <tr>
16 <th>Position</th>
19 <th>Position</th>
17 <th>Message</th>
20 <th>Message</th>
18 </tr>
21 </tr>
19 <% @import.unsaved_items.each do |item| %>
22 </thead>
23 <tbody>
24 <% @import.unsaved_items.each do |item| %>
20 <tr>
25 <tr>
21 <td><%= item.position %></td>
26 <td><%= item.position %></td>
22 <td><%= simple_format_without_paragraph item.message %></td>
27 <td><%= simple_format_without_paragraph item.message %></td>
23 </tr>
28 </tr>
24 <% end %>
29 <% end %>
30 </tbody>
25 </table>
31 </table>
26 <% end %>
32 <% end %>
27
33
@@ -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;status
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;new
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;new
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;assigned
@@ -184,6 +184,8 class ImportsControllerTest < ActionController::TestCase
184 get :show, :id => import.to_param
184 get :show, :id => import.to_param
185 assert_response :success
185 assert_response :success
186 assert_template 'show'
186 assert_template 'show'
187 assert_select 'ul#saved-items'
188 assert_select 'ul#saved-items li', import.saved_items.count
187 assert_select 'table#unsaved-items', 0
189 assert_select 'table#unsaved-items', 0
188 end
190 end
189
191
@@ -197,5 +199,6 class ImportsControllerTest < ActionController::TestCase
197 assert_response :success
199 assert_response :success
198 assert_template 'show'
200 assert_template 'show'
199 assert_select 'table#unsaved-items'
201 assert_select 'table#unsaved-items'
202 assert_select 'table#unsaved-items tbody tr', import.unsaved_items.count
200 end
203 end
201 end
204 end
@@ -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,46 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
92 def test_status_should_be_set
93 import = generate_import_with_mapping
94 import.mapping.merge!('status' => '14')
95 import.save!
96
97 issues = new_records(Issue, 3) { import.run }
98 assert_equal ['New', 'New', 'Assigned'], issues.map(&:status).map(&:name)
99 end
100
61 def test_parent_should_be_set
101 def test_parent_should_be_set
62 import = generate_import_with_mapping
102 import = generate_import_with_mapping
63 import.mapping.merge!('parent_issue_id' => '5')
103 import.mapping.merge!('parent_issue_id' => '5')
@@ -101,7 +141,7 class IssueImportTest < ActiveSupport::TestCase
101 field = IssueCustomField.generate!(:field_format => 'date', :is_for_all => true, :trackers => Tracker.all)
141 field = IssueCustomField.generate!(:field_format => 'date', :is_for_all => true, :trackers => Tracker.all)
102 import = generate_import_with_mapping('import_dates.csv')
142 import = generate_import_with_mapping('import_dates.csv')
103 import.settings.merge!('date_format' => Import::DATE_FORMATS[1])
143 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')
144 import.mapping.merge!('tracker' => 'value:1', 'subject' => '0', 'start_date' => '1', 'due_date' => '2', "cf_#{field.id}" => '3')
105 import.save!
145 import.save!
106
146
107 issue = new_record(Issue) { import.run } # only 1 valid issue
147 issue = new_record(Issue) { import.run } # only 1 valid issue
General Comments 0
You need to be logged in to leave comments. Login now