@@ -0,0 +1,94 | |||||
|
1 | class IssueMovesController < ApplicationController | |||
|
2 | default_search_scope :issues | |||
|
3 | before_filter :find_issues | |||
|
4 | before_filter :authorize | |||
|
5 | ||||
|
6 | def new | |||
|
7 | prepare_for_issue_move | |||
|
8 | render :layout => false if request.xhr? | |||
|
9 | end | |||
|
10 | ||||
|
11 | def create | |||
|
12 | prepare_for_issue_move | |||
|
13 | ||||
|
14 | if request.post? | |||
|
15 | new_tracker = params[:new_tracker_id].blank? ? nil : @target_project.trackers.find_by_id(params[:new_tracker_id]) | |||
|
16 | unsaved_issue_ids = [] | |||
|
17 | moved_issues = [] | |||
|
18 | @issues.each do |issue| | |||
|
19 | issue.reload | |||
|
20 | issue.init_journal(User.current) | |||
|
21 | call_hook(:controller_issues_move_before_save, { :params => params, :issue => issue, :target_project => @target_project, :copy => !!@copy }) | |||
|
22 | if r = issue.move_to_project(@target_project, new_tracker, {:copy => @copy, :attributes => extract_changed_attributes_for_move(params)}) | |||
|
23 | moved_issues << r | |||
|
24 | else | |||
|
25 | unsaved_issue_ids << issue.id | |||
|
26 | end | |||
|
27 | end | |||
|
28 | set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids) | |||
|
29 | ||||
|
30 | if params[:follow] | |||
|
31 | if @issues.size == 1 && moved_issues.size == 1 | |||
|
32 | redirect_to :controller => 'issues', :action => 'show', :id => moved_issues.first | |||
|
33 | else | |||
|
34 | redirect_to :controller => 'issues', :action => 'index', :project_id => (@target_project || @project) | |||
|
35 | end | |||
|
36 | else | |||
|
37 | redirect_to :controller => 'issues', :action => 'index', :project_id => @project | |||
|
38 | end | |||
|
39 | return | |||
|
40 | end | |||
|
41 | end | |||
|
42 | ||||
|
43 | private | |||
|
44 | ||||
|
45 | def prepare_for_issue_move | |||
|
46 | @issues.sort! | |||
|
47 | @copy = params[:copy_options] && params[:copy_options][:copy] | |||
|
48 | @allowed_projects = Issue.allowed_target_projects_on_move | |||
|
49 | @target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id] | |||
|
50 | @target_project ||= @project | |||
|
51 | @trackers = @target_project.trackers | |||
|
52 | @available_statuses = Workflow.available_statuses(@project) | |||
|
53 | end | |||
|
54 | ||||
|
55 | # Filter for bulk operations | |||
|
56 | # TODO: duplicated in IssuesController | |||
|
57 | def find_issues | |||
|
58 | @issues = Issue.find_all_by_id(params[:id] || params[:ids]) | |||
|
59 | raise ActiveRecord::RecordNotFound if @issues.empty? | |||
|
60 | projects = @issues.collect(&:project).compact.uniq | |||
|
61 | if projects.size == 1 | |||
|
62 | @project = projects.first | |||
|
63 | else | |||
|
64 | # TODO: let users bulk edit/move/destroy issues from different projects | |||
|
65 | render_error 'Can not bulk edit/move/destroy issues from different projects' | |||
|
66 | return false | |||
|
67 | end | |||
|
68 | rescue ActiveRecord::RecordNotFound | |||
|
69 | render_404 | |||
|
70 | end | |||
|
71 | ||||
|
72 | # TODO: duplicated in IssuesController | |||
|
73 | def set_flash_from_bulk_issue_save(issues, unsaved_issue_ids) | |||
|
74 | if unsaved_issue_ids.empty? | |||
|
75 | flash[:notice] = l(:notice_successful_update) unless issues.empty? | |||
|
76 | else | |||
|
77 | flash[:error] = l(:notice_failed_to_save_issues, | |||
|
78 | :count => unsaved_issue_ids.size, | |||
|
79 | :total => issues.size, | |||
|
80 | :ids => '#' + unsaved_issue_ids.join(', #')) | |||
|
81 | end | |||
|
82 | end | |||
|
83 | ||||
|
84 | def extract_changed_attributes_for_move(params) | |||
|
85 | changed_attributes = {} | |||
|
86 | [:assigned_to_id, :status_id, :start_date, :due_date].each do |valid_attribute| | |||
|
87 | unless params[valid_attribute].blank? | |||
|
88 | changed_attributes[valid_attribute] = (params[valid_attribute] == 'none' ? nil : params[valid_attribute]) | |||
|
89 | end | |||
|
90 | end | |||
|
91 | changed_attributes | |||
|
92 | end | |||
|
93 | ||||
|
94 | end |
@@ -0,0 +1,99 | |||||
|
1 | require 'test_helper' | |||
|
2 | ||||
|
3 | class IssueMovesControllerTest < ActionController::TestCase | |||
|
4 | fixtures :all | |||
|
5 | ||||
|
6 | def setup | |||
|
7 | User.current = nil | |||
|
8 | end | |||
|
9 | ||||
|
10 | def test_create_one_issue_to_another_project | |||
|
11 | @request.session[:user_id] = 2 | |||
|
12 | post :create, :id => 1, :new_project_id => 2, :tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => '' | |||
|
13 | assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook' | |||
|
14 | assert_equal 2, Issue.find(1).project_id | |||
|
15 | end | |||
|
16 | ||||
|
17 | def test_create_one_issue_to_another_project_should_follow_when_needed | |||
|
18 | @request.session[:user_id] = 2 | |||
|
19 | post :create, :id => 1, :new_project_id => 2, :follow => '1' | |||
|
20 | assert_redirected_to '/issues/1' | |||
|
21 | end | |||
|
22 | ||||
|
23 | def test_bulk_create_to_another_project | |||
|
24 | @request.session[:user_id] = 2 | |||
|
25 | post :create, :ids => [1, 2], :new_project_id => 2 | |||
|
26 | assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook' | |||
|
27 | # Issues moved to project 2 | |||
|
28 | assert_equal 2, Issue.find(1).project_id | |||
|
29 | assert_equal 2, Issue.find(2).project_id | |||
|
30 | # No tracker change | |||
|
31 | assert_equal 1, Issue.find(1).tracker_id | |||
|
32 | assert_equal 2, Issue.find(2).tracker_id | |||
|
33 | end | |||
|
34 | ||||
|
35 | def test_bulk_create_to_another_tracker | |||
|
36 | @request.session[:user_id] = 2 | |||
|
37 | post :create, :ids => [1, 2], :new_tracker_id => 2 | |||
|
38 | assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook' | |||
|
39 | assert_equal 2, Issue.find(1).tracker_id | |||
|
40 | assert_equal 2, Issue.find(2).tracker_id | |||
|
41 | end | |||
|
42 | ||||
|
43 | def test_bulk_copy_to_another_project | |||
|
44 | @request.session[:user_id] = 2 | |||
|
45 | assert_difference 'Issue.count', 2 do | |||
|
46 | assert_no_difference 'Project.find(1).issues.count' do | |||
|
47 | post :create, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'} | |||
|
48 | end | |||
|
49 | end | |||
|
50 | assert_redirected_to 'projects/ecookbook/issues' | |||
|
51 | end | |||
|
52 | ||||
|
53 | context "#create via bulk copy" do | |||
|
54 | should "allow not changing the issue's attributes" do | |||
|
55 | @request.session[:user_id] = 2 | |||
|
56 | issue_before_move = Issue.find(1) | |||
|
57 | assert_difference 'Issue.count', 1 do | |||
|
58 | assert_no_difference 'Project.find(1).issues.count' do | |||
|
59 | post :create, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => '' | |||
|
60 | end | |||
|
61 | end | |||
|
62 | issue_after_move = Issue.first(:order => 'id desc', :conditions => {:project_id => 2}) | |||
|
63 | assert_equal issue_before_move.tracker_id, issue_after_move.tracker_id | |||
|
64 | assert_equal issue_before_move.status_id, issue_after_move.status_id | |||
|
65 | assert_equal issue_before_move.assigned_to_id, issue_after_move.assigned_to_id | |||
|
66 | end | |||
|
67 | ||||
|
68 | should "allow changing the issue's attributes" do | |||
|
69 | # Fixes random test failure with Mysql | |||
|
70 | # where Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2}) doesn't return the expected results | |||
|
71 | Issue.delete_all("project_id=2") | |||
|
72 | ||||
|
73 | @request.session[:user_id] = 2 | |||
|
74 | assert_difference 'Issue.count', 2 do | |||
|
75 | assert_no_difference 'Project.find(1).issues.count' do | |||
|
76 | post :create, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => 4, :status_id => 3, :start_date => '2009-12-01', :due_date => '2009-12-31' | |||
|
77 | end | |||
|
78 | end | |||
|
79 | ||||
|
80 | copied_issues = Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2}) | |||
|
81 | assert_equal 2, copied_issues.size | |||
|
82 | copied_issues.each do |issue| | |||
|
83 | assert_equal 2, issue.project_id, "Project is incorrect" | |||
|
84 | assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect" | |||
|
85 | assert_equal 3, issue.status_id, "Status is incorrect" | |||
|
86 | assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect" | |||
|
87 | assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect" | |||
|
88 | end | |||
|
89 | end | |||
|
90 | end | |||
|
91 | ||||
|
92 | def test_copy_to_another_project_should_follow_when_needed | |||
|
93 | @request.session[:user_id] = 2 | |||
|
94 | post :create, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :follow => '1' | |||
|
95 | issue = Issue.first(:order => 'id DESC') | |||
|
96 | assert_redirected_to :controller => 'issues', :action => 'show', :id => issue | |||
|
97 | end | |||
|
98 | ||||
|
99 | end |
@@ -249,44 +249,6 class IssuesController < ApplicationController | |||||
249 | @available_statuses = Workflow.available_statuses(@project) |
|
249 | @available_statuses = Workflow.available_statuses(@project) | |
250 | @custom_fields = @project.all_issue_custom_fields |
|
250 | @custom_fields = @project.all_issue_custom_fields | |
251 | end |
|
251 | end | |
252 |
|
||||
253 | def move |
|
|||
254 | prepare_for_issue_move |
|
|||
255 | render :layout => false if request.xhr? |
|
|||
256 | end |
|
|||
257 |
|
||||
258 | # TODO: more descriptive name? move to separate controller like IssueMovesController? |
|
|||
259 | def perform_move |
|
|||
260 | prepare_for_issue_move |
|
|||
261 |
|
||||
262 | if request.post? |
|
|||
263 | new_tracker = params[:new_tracker_id].blank? ? nil : @target_project.trackers.find_by_id(params[:new_tracker_id]) |
|
|||
264 | unsaved_issue_ids = [] |
|
|||
265 | moved_issues = [] |
|
|||
266 | @issues.each do |issue| |
|
|||
267 | issue.reload |
|
|||
268 | issue.init_journal(User.current) |
|
|||
269 | call_hook(:controller_issues_move_before_save, { :params => params, :issue => issue, :target_project => @target_project, :copy => !!@copy }) |
|
|||
270 | if r = issue.move_to_project(@target_project, new_tracker, {:copy => @copy, :attributes => extract_changed_attributes_for_move(params)}) |
|
|||
271 | moved_issues << r |
|
|||
272 | else |
|
|||
273 | unsaved_issue_ids << issue.id |
|
|||
274 | end |
|
|||
275 | end |
|
|||
276 | set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids) |
|
|||
277 |
|
||||
278 | if params[:follow] |
|
|||
279 | if @issues.size == 1 && moved_issues.size == 1 |
|
|||
280 | redirect_to :controller => 'issues', :action => 'show', :id => moved_issues.first |
|
|||
281 | else |
|
|||
282 | redirect_to :controller => 'issues', :action => 'index', :project_id => (@target_project || @project) |
|
|||
283 | end |
|
|||
284 | else |
|
|||
285 | redirect_to :controller => 'issues', :action => 'index', :project_id => @project |
|
|||
286 | end |
|
|||
287 | return |
|
|||
288 | end |
|
|||
289 | end |
|
|||
290 |
|
252 | |||
291 | def destroy |
|
253 | def destroy | |
292 | @hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f |
|
254 | @hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f | |
@@ -462,16 +424,6 private | |||||
462 | @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true) |
|
424 | @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true) | |
463 | end |
|
425 | end | |
464 |
|
426 | |||
465 | def prepare_for_issue_move |
|
|||
466 | @issues.sort! |
|
|||
467 | @copy = params[:copy_options] && params[:copy_options][:copy] |
|
|||
468 | @allowed_projects = Issue.allowed_target_projects_on_move |
|
|||
469 | @target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id] |
|
|||
470 | @target_project ||= @project |
|
|||
471 | @trackers = @target_project.trackers |
|
|||
472 | @available_statuses = Workflow.available_statuses(@project) |
|
|||
473 | end |
|
|||
474 |
|
||||
475 | def set_flash_from_bulk_issue_save(issues, unsaved_issue_ids) |
|
427 | def set_flash_from_bulk_issue_save(issues, unsaved_issue_ids) | |
476 | if unsaved_issue_ids.empty? |
|
428 | if unsaved_issue_ids.empty? | |
477 | flash[:notice] = l(:notice_successful_update) unless issues.empty? |
|
429 | flash[:notice] = l(:notice_successful_update) unless issues.empty? | |
@@ -489,14 +441,4 private | |||||
489 | return false |
|
441 | return false | |
490 | end |
|
442 | end | |
491 | end |
|
443 | end | |
492 |
|
||||
493 | def extract_changed_attributes_for_move(params) |
|
|||
494 | changed_attributes = {} |
|
|||
495 | [:assigned_to_id, :status_id, :start_date, :due_date].each do |valid_attribute| |
|
|||
496 | unless params[valid_attribute].blank? |
|
|||
497 | changed_attributes[valid_attribute] = (params[valid_attribute] == 'none' ? nil : params[valid_attribute]) |
|
|||
498 | end |
|
|||
499 | end |
|
|||
500 | changed_attributes |
|
|||
501 | end |
|
|||
502 | end |
|
444 | end |
@@ -6,14 +6,14 | |||||
6 | <% end -%> |
|
6 | <% end -%> | |
7 | </ul> |
|
7 | </ul> | |
8 |
|
8 | |||
9 |
<% form_tag({:action => ' |
|
9 | <% form_tag({:action => 'create'}, :id => 'move_form') do %> | |
10 | <%= @issues.collect {|i| hidden_field_tag('ids[]', i.id)}.join %> |
|
10 | <%= @issues.collect {|i| hidden_field_tag('ids[]', i.id)}.join %> | |
11 |
|
11 | |||
12 | <div class="box tabular"> |
|
12 | <div class="box tabular"> | |
13 | <p><label for="new_project_id"><%=l(:field_project)%>:</label> |
|
13 | <p><label for="new_project_id"><%=l(:field_project)%>:</label> | |
14 | <%= select_tag "new_project_id", |
|
14 | <%= select_tag "new_project_id", | |
15 | project_tree_options_for_select(@allowed_projects, :selected => @target_project), |
|
15 | project_tree_options_for_select(@allowed_projects, :selected => @target_project), | |
16 |
:onchange => remote_function(:url => { :action => ' |
|
16 | :onchange => remote_function(:url => { :action => 'new' }, | |
17 | :method => :get, |
|
17 | :method => :get, | |
18 | :update => 'content', |
|
18 | :update => 'content', | |
19 | :with => "Form.serialize('move_form')") %></p> |
|
19 | :with => "Form.serialize('move_form')") %></p> |
@@ -4,7 +4,7 | |||||
4 | <% replace_watcher ||= 'watcher' %> |
|
4 | <% replace_watcher ||= 'watcher' %> | |
5 | <%= watcher_tag(@issue, User.current, {:id => replace_watcher, :replace => ['watcher','watcher2']}) %> |
|
5 | <%= watcher_tag(@issue, User.current, {:id => replace_watcher, :replace => ['watcher','watcher2']}) %> | |
6 | <%= link_to_if_authorized l(:button_duplicate), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue }, :class => 'icon icon-duplicate' %> |
|
6 | <%= link_to_if_authorized l(:button_duplicate), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue }, :class => 'icon icon-duplicate' %> | |
7 |
<%= link_to_if_authorized l(:button_copy), |
|
7 | <%= link_to_if_authorized l(:button_copy), new_issue_move_path(:id => @issue, :copy_options => {:copy => 't'}), :class => 'icon icon-copy' %> | |
8 |
<%= link_to_if_authorized l(:button_move), |
|
8 | <%= link_to_if_authorized l(:button_move), new_issue_move_path(:id => @issue), :class => 'icon icon-move' %> | |
9 | <%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %> |
|
9 | <%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %> | |
10 | </div> |
|
10 | </div> |
@@ -102,9 +102,9 | |||||
102 | <li><%= context_menu_link l(:button_duplicate), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue}, |
|
102 | <li><%= context_menu_link l(:button_duplicate), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue}, | |
103 | :class => 'icon-duplicate', :disabled => !@can[:copy] %></li> |
|
103 | :class => 'icon-duplicate', :disabled => !@can[:copy] %></li> | |
104 | <% end %> |
|
104 | <% end %> | |
105 |
<li><%= context_menu_link l(:button_copy), |
|
105 | <li><%= context_menu_link l(:button_copy), new_issue_move_path(:ids => @issues.collect(&:id), :copy_options => {:copy => 't'}), | |
106 | :class => 'icon-copy', :disabled => !@can[:move] %></li> |
|
106 | :class => 'icon-copy', :disabled => !@can[:move] %></li> | |
107 |
<li><%= context_menu_link l(:button_move), |
|
107 | <li><%= context_menu_link l(:button_move), new_issue_move_path(:ids => @issues.collect(&:id)), | |
108 | :class => 'icon-move', :disabled => !@can[:move] %></li> |
|
108 | :class => 'icon-move', :disabled => !@can[:move] %></li> | |
109 | <li><%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :ids => @issues.collect(&:id)}, |
|
109 | <li><%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :ids => @issues.collect(&:id)}, | |
110 | :method => :post, :confirm => l(:text_issues_destroy_confirmation), :class => 'icon-del', :disabled => !@can[:delete] %></li> |
|
110 | :method => :post, :confirm => l(:text_issues_destroy_confirmation), :class => 'icon-del', :disabled => !@can[:delete] %></li> |
@@ -102,7 +102,9 ActionController::Routing::Routes.draw do |map| | |||||
102 | document_actions.connect 'documents/:id/:action', :action => /destroy|edit/ |
|
102 | document_actions.connect 'documents/:id/:action', :action => /destroy|edit/ | |
103 | end |
|
103 | end | |
104 | end |
|
104 | end | |
105 |
|
105 | |||
|
106 | map.resources :issue_moves, :only => [:new, :create], :path_prefix => '/issues', :as => 'move' | |||
|
107 | ||||
106 | map.with_options :controller => 'issues' do |issues_routes| |
|
108 | map.with_options :controller => 'issues' do |issues_routes| | |
107 | issues_routes.with_options :conditions => {:method => :get} do |issues_views| |
|
109 | issues_routes.with_options :conditions => {:method => :get} do |issues_views| | |
108 | issues_views.connect 'issues', :action => 'index' |
|
110 | issues_views.connect 'issues', :action => 'index' | |
@@ -116,7 +118,6 ActionController::Routing::Routes.draw do |map| | |||||
116 | issues_views.connect 'issues/:id', :action => 'show', :id => /\d+/ |
|
118 | issues_views.connect 'issues/:id', :action => 'show', :id => /\d+/ | |
117 | issues_views.connect 'issues/:id.:format', :action => 'show', :id => /\d+/ |
|
119 | issues_views.connect 'issues/:id.:format', :action => 'show', :id => /\d+/ | |
118 | issues_views.connect 'issues/:id/edit', :action => 'edit', :id => /\d+/ |
|
120 | issues_views.connect 'issues/:id/edit', :action => 'edit', :id => /\d+/ | |
119 | issues_views.connect 'issues/:id/move', :action => 'move', :id => /\d+/ |
|
|||
120 | end |
|
121 | end | |
121 | issues_routes.with_options :conditions => {:method => :post} do |issues_actions| |
|
122 | issues_routes.with_options :conditions => {:method => :post} do |issues_actions| | |
122 | issues_actions.connect 'issues', :action => 'index' |
|
123 | issues_actions.connect 'issues', :action => 'index' | |
@@ -124,7 +125,7 ActionController::Routing::Routes.draw do |map| | |||||
124 | issues_actions.connect 'projects/:project_id/issues/gantt', :controller => 'gantts', :action => 'show' |
|
125 | issues_actions.connect 'projects/:project_id/issues/gantt', :controller => 'gantts', :action => 'show' | |
125 | issues_actions.connect 'projects/:project_id/issues/calendar', :controller => 'calendars', :action => 'show' |
|
126 | issues_actions.connect 'projects/:project_id/issues/calendar', :controller => 'calendars', :action => 'show' | |
126 | issues_actions.connect 'issues/:id/quoted', :action => 'reply', :id => /\d+/ |
|
127 | issues_actions.connect 'issues/:id/quoted', :action => 'reply', :id => /\d+/ | |
127 |
issues_actions.connect 'issues/:id/:action', :action => /edit| |
|
128 | issues_actions.connect 'issues/:id/:action', :action => /edit|destroy/, :id => /\d+/ | |
128 | issues_actions.connect 'issues.:format', :action => 'create', :format => /xml/ |
|
129 | issues_actions.connect 'issues.:format', :action => 'create', :format => /xml/ | |
129 | end |
|
130 | end | |
130 | issues_routes.with_options :conditions => {:method => :put} do |issues_actions| |
|
131 | issues_routes.with_options :conditions => {:method => :put} do |issues_actions| | |
@@ -138,7 +139,7 ActionController::Routing::Routes.draw do |map| | |||||
138 | issues_routes.connect 'issues/calendar', :controller => 'calendars', :action => 'show' |
|
139 | issues_routes.connect 'issues/calendar', :controller => 'calendars', :action => 'show' | |
139 | issues_routes.connect 'issues/:action' |
|
140 | issues_routes.connect 'issues/:action' | |
140 | end |
|
141 | end | |
141 |
|
142 | |||
142 | map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations| |
|
143 | map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations| | |
143 | relations.connect 'issues/:issue_id/relations/:id', :action => 'new' |
|
144 | relations.connect 'issues/:issue_id/relations/:id', :action => 'new' | |
144 | relations.connect 'issues/:issue_id/relations/:id/destroy', :action => 'destroy' |
|
145 | relations.connect 'issues/:issue_id/relations/:id/destroy', :action => 'destroy' |
@@ -69,7 +69,7 Redmine::AccessControl.map do |map| | |||||
69 | map.permission :add_issue_notes, {:issues => [:edit, :update, :reply]} |
|
69 | map.permission :add_issue_notes, {:issues => [:edit, :update, :reply]} | |
70 | map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin |
|
70 | map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin | |
71 | map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin |
|
71 | map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin | |
72 |
map.permission :move_issues, {:issues => [: |
|
72 | map.permission :move_issues, {:issue_moves => [:new, :create]}, :require => :loggedin | |
73 | map.permission :delete_issues, {:issues => :destroy}, :require => :member |
|
73 | map.permission :delete_issues, {:issues => :destroy}, :require => :member | |
74 | # Queries |
|
74 | # Queries | |
75 | map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member |
|
75 | map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member |
@@ -1037,95 +1037,6 class IssuesControllerTest < ActionController::TestCase | |||||
1037 | assert_response :redirect |
|
1037 | assert_response :redirect | |
1038 | assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier |
|
1038 | assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier | |
1039 | end |
|
1039 | end | |
1040 |
|
||||
1041 | def test_perform_move_one_issue_to_another_project |
|
|||
1042 | @request.session[:user_id] = 2 |
|
|||
1043 | post :perform_move, :id => 1, :new_project_id => 2, :tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => '' |
|
|||
1044 | assert_redirected_to :action => 'index', :project_id => 'ecookbook' |
|
|||
1045 | assert_equal 2, Issue.find(1).project_id |
|
|||
1046 | end |
|
|||
1047 |
|
||||
1048 | def test_perform_move_one_issue_to_another_project_should_follow_when_needed |
|
|||
1049 | @request.session[:user_id] = 2 |
|
|||
1050 | post :perform_move, :id => 1, :new_project_id => 2, :follow => '1' |
|
|||
1051 | assert_redirected_to '/issues/1' |
|
|||
1052 | end |
|
|||
1053 |
|
||||
1054 | def test_bulk_perform_move_to_another_project |
|
|||
1055 | @request.session[:user_id] = 2 |
|
|||
1056 | post :perform_move, :ids => [1, 2], :new_project_id => 2 |
|
|||
1057 | assert_redirected_to :action => 'index', :project_id => 'ecookbook' |
|
|||
1058 | # Issues moved to project 2 |
|
|||
1059 | assert_equal 2, Issue.find(1).project_id |
|
|||
1060 | assert_equal 2, Issue.find(2).project_id |
|
|||
1061 | # No tracker change |
|
|||
1062 | assert_equal 1, Issue.find(1).tracker_id |
|
|||
1063 | assert_equal 2, Issue.find(2).tracker_id |
|
|||
1064 | end |
|
|||
1065 |
|
||||
1066 | def test_bulk_perform_move_to_another_tracker |
|
|||
1067 | @request.session[:user_id] = 2 |
|
|||
1068 | post :perform_move, :ids => [1, 2], :new_tracker_id => 2 |
|
|||
1069 | assert_redirected_to :action => 'index', :project_id => 'ecookbook' |
|
|||
1070 | assert_equal 2, Issue.find(1).tracker_id |
|
|||
1071 | assert_equal 2, Issue.find(2).tracker_id |
|
|||
1072 | end |
|
|||
1073 |
|
||||
1074 | def test_bulk_copy_to_another_project |
|
|||
1075 | @request.session[:user_id] = 2 |
|
|||
1076 | assert_difference 'Issue.count', 2 do |
|
|||
1077 | assert_no_difference 'Project.find(1).issues.count' do |
|
|||
1078 | post :perform_move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'} |
|
|||
1079 | end |
|
|||
1080 | end |
|
|||
1081 | assert_redirected_to 'projects/ecookbook/issues' |
|
|||
1082 | end |
|
|||
1083 |
|
||||
1084 | context "#perform_move via bulk copy" do |
|
|||
1085 | should "allow not changing the issue's attributes" do |
|
|||
1086 | @request.session[:user_id] = 2 |
|
|||
1087 | issue_before_move = Issue.find(1) |
|
|||
1088 | assert_difference 'Issue.count', 1 do |
|
|||
1089 | assert_no_difference 'Project.find(1).issues.count' do |
|
|||
1090 | post :perform_move, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => '' |
|
|||
1091 | end |
|
|||
1092 | end |
|
|||
1093 | issue_after_move = Issue.first(:order => 'id desc', :conditions => {:project_id => 2}) |
|
|||
1094 | assert_equal issue_before_move.tracker_id, issue_after_move.tracker_id |
|
|||
1095 | assert_equal issue_before_move.status_id, issue_after_move.status_id |
|
|||
1096 | assert_equal issue_before_move.assigned_to_id, issue_after_move.assigned_to_id |
|
|||
1097 | end |
|
|||
1098 |
|
||||
1099 | should "allow changing the issue's attributes" do |
|
|||
1100 | # Fixes random test failure with Mysql |
|
|||
1101 | # where Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2}) doesn't return the expected results |
|
|||
1102 | Issue.delete_all("project_id=2") |
|
|||
1103 |
|
||||
1104 | @request.session[:user_id] = 2 |
|
|||
1105 | assert_difference 'Issue.count', 2 do |
|
|||
1106 | assert_no_difference 'Project.find(1).issues.count' do |
|
|||
1107 | post :perform_move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => 4, :status_id => 3, :start_date => '2009-12-01', :due_date => '2009-12-31' |
|
|||
1108 | end |
|
|||
1109 | end |
|
|||
1110 |
|
||||
1111 | copied_issues = Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2}) |
|
|||
1112 | assert_equal 2, copied_issues.size |
|
|||
1113 | copied_issues.each do |issue| |
|
|||
1114 | assert_equal 2, issue.project_id, "Project is incorrect" |
|
|||
1115 | assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect" |
|
|||
1116 | assert_equal 3, issue.status_id, "Status is incorrect" |
|
|||
1117 | assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect" |
|
|||
1118 | assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect" |
|
|||
1119 | end |
|
|||
1120 | end |
|
|||
1121 | end |
|
|||
1122 |
|
||||
1123 | def test_copy_to_another_project_should_follow_when_needed |
|
|||
1124 | @request.session[:user_id] = 2 |
|
|||
1125 | post :perform_move, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :follow => '1' |
|
|||
1126 | issue = Issue.first(:order => 'id DESC') |
|
|||
1127 | assert_redirected_to :controller => 'issues', :action => 'show', :id => issue |
|
|||
1128 | end |
|
|||
1129 |
|
1040 | |||
1130 | def test_context_menu_one_issue |
|
1041 | def test_context_menu_one_issue | |
1131 | @request.session[:user_id] = 2 |
|
1042 | @request.session[:user_id] = 2 | |
@@ -1156,10 +1067,10 class IssuesControllerTest < ActionController::TestCase | |||||
1156 | :attributes => { :href => '/projects/ecookbook/issues/1/copy', |
|
1067 | :attributes => { :href => '/projects/ecookbook/issues/1/copy', | |
1157 | :class => 'icon-duplicate' } |
|
1068 | :class => 'icon-duplicate' } | |
1158 | assert_tag :tag => 'a', :content => 'Copy', |
|
1069 | assert_tag :tag => 'a', :content => 'Copy', | |
1159 | :attributes => { :href => '/issues/move?copy_options%5Bcopy%5D=t&ids%5B%5D=1', |
|
1070 | :attributes => { :href => '/issues/move/new?copy_options%5Bcopy%5D=t&ids%5B%5D=1', | |
1160 | :class => 'icon-copy' } |
|
1071 | :class => 'icon-copy' } | |
1161 | assert_tag :tag => 'a', :content => 'Move', |
|
1072 | assert_tag :tag => 'a', :content => 'Move', | |
1162 | :attributes => { :href => '/issues/move?ids%5B%5D=1', |
|
1073 | :attributes => { :href => '/issues/move/new?ids%5B%5D=1', | |
1163 | :class => 'icon-move' } |
|
1074 | :class => 'icon-move' } | |
1164 | assert_tag :tag => 'a', :content => 'Delete', |
|
1075 | assert_tag :tag => 'a', :content => 'Delete', | |
1165 | :attributes => { :href => '/issues/destroy?ids%5B%5D=1', |
|
1076 | :attributes => { :href => '/issues/destroy?ids%5B%5D=1', | |
@@ -1190,10 +1101,10 class IssuesControllerTest < ActionController::TestCase | |||||
1190 | :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&ids%5B%5D=2&issue%5Bassigned_to_id%5D=3', |
|
1101 | :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&ids%5B%5D=2&issue%5Bassigned_to_id%5D=3', | |
1191 | :class => '' } |
|
1102 | :class => '' } | |
1192 | assert_tag :tag => 'a', :content => 'Copy', |
|
1103 | assert_tag :tag => 'a', :content => 'Copy', | |
1193 | :attributes => { :href => '/issues/move?copy_options%5Bcopy%5D=t&ids%5B%5D=1&ids%5B%5D=2', |
|
1104 | :attributes => { :href => '/issues/move/new?copy_options%5Bcopy%5D=t&ids%5B%5D=1&ids%5B%5D=2', | |
1194 | :class => 'icon-copy' } |
|
1105 | :class => 'icon-copy' } | |
1195 | assert_tag :tag => 'a', :content => 'Move', |
|
1106 | assert_tag :tag => 'a', :content => 'Move', | |
1196 | :attributes => { :href => '/issues/move?ids%5B%5D=1&ids%5B%5D=2', |
|
1107 | :attributes => { :href => '/issues/move/new?ids%5B%5D=1&ids%5B%5D=2', | |
1197 | :class => 'icon-move' } |
|
1108 | :class => 'icon-move' } | |
1198 | assert_tag :tag => 'a', :content => 'Delete', |
|
1109 | assert_tag :tag => 'a', :content => 'Delete', | |
1199 | :attributes => { :href => '/issues/destroy?ids%5B%5D=1&ids%5B%5D=2', |
|
1110 | :attributes => { :href => '/issues/destroy?ids%5B%5D=1&ids%5B%5D=2', |
@@ -85,8 +85,8 class RoutingTest < ActionController::IntegrationTest | |||||
85 | # Extra actions |
|
85 | # Extra actions | |
86 | should_route :get, "/projects/23/issues/64/copy", :controller => 'issues', :action => 'new', :project_id => '23', :copy_from => '64' |
|
86 | should_route :get, "/projects/23/issues/64/copy", :controller => 'issues', :action => 'new', :project_id => '23', :copy_from => '64' | |
87 |
|
87 | |||
88 |
should_route :get, "/issues/ |
|
88 | should_route :get, "/issues/move/new", :controller => 'issue_moves', :action => 'new' | |
89 |
should_route :post, "/issues/ |
|
89 | should_route :post, "/issues/move", :controller => 'issue_moves', :action => 'create' | |
90 |
|
90 | |||
91 | should_route :post, "/issues/1/quoted", :controller => 'issues', :action => 'reply', :id => '1' |
|
91 | should_route :post, "/issues/1/quoted", :controller => 'issues', :action => 'reply', :id => '1' | |
92 |
|
92 |
General Comments 0
You need to be logged in to leave comments.
Login now