##// END OF EJS Templates
Allow mass status update through context menu. #3411...
Jean-Baptiste Barth -
r3941:a2ce6e236c39
parent child
Show More
@@ -1,33 +1,39
1 1 class ContextMenusController < ApplicationController
2 2 helper :watchers
3 3
4 4 def issues
5 5 @issues = Issue.find_all_by_id(params[:ids], :include => :project)
6 6 if (@issues.size == 1)
7 7 @issue = @issues.first
8 8 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
9 else
10 @allowed_statuses = @issues.map do |i|
11 i.new_statuses_allowed_to(User.current)
12 end.inject do |memo,s|
13 memo & s
14 end
9 15 end
10 16 projects = @issues.collect(&:project).compact.uniq
11 17 @project = projects.first if projects.size == 1
12 18
13 19 @can = {:edit => (@project && User.current.allowed_to?(:edit_issues, @project)),
14 20 :log_time => (@project && User.current.allowed_to?(:log_time, @project)),
15 21 :update => (@project && (User.current.allowed_to?(:edit_issues, @project) || (User.current.allowed_to?(:change_status, @project) && @allowed_statuses && !@allowed_statuses.empty?))),
16 22 :move => (@project && User.current.allowed_to?(:move_issues, @project)),
17 23 :copy => (@issue && @project.trackers.include?(@issue.tracker) && User.current.allowed_to?(:add_issues, @project)),
18 24 :delete => (@project && User.current.allowed_to?(:delete_issues, @project))
19 25 }
20 26 if @project
21 27 @assignables = @project.assignable_users
22 28 @assignables << @issue.assigned_to if @issue && @issue.assigned_to && !@assignables.include?(@issue.assigned_to)
23 29 @trackers = @project.trackers
24 30 end
25 31
26 32 @priorities = IssuePriority.all.reverse
27 33 @statuses = IssueStatus.find(:all, :order => 'position')
28 34 @back = back_url
29 35
30 36 render :layout => false
31 37 end
32 38
33 39 end
@@ -1,113 +1,116
1 1 <ul>
2 2 <%= call_hook(:view_issues_context_menu_start, {:issues => @issues, :can => @can, :back => @back }) %>
3 3
4 4 <% if !@issue.nil? -%>
5 5 <li><%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue},
6 6 :class => 'icon-edit', :disabled => !@can[:edit] %></li>
7 <% else %>
8 <li><%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id)},
9 :class => 'icon-edit', :disabled => !@can[:edit] %></li>
10 <% end %>
11
12 <% unless @allowed_statuses.empty? %>
7 13 <li class="folder">
8 14 <a href="#" class="submenu" onclick="return false;"><%= l(:field_status) %></a>
9 15 <ul>
10 16 <% @statuses.each do |s| -%>
11 <li><%= context_menu_link s.name, {:controller => 'issues', :action => 'update', :id => @issue, :issue => {:status_id => s}, :back_url => @back}, :method => :put,
12 :selected => (s == @issue.status), :disabled => !(@can[:update] && @allowed_statuses.include?(s)) %></li>
17 <li><%= context_menu_link s.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {:status_id => s}, :back_url => @back}, :method => :post,
18 :selected => (@issue && s == @issue.status), :disabled => !(@can[:update] && @allowed_statuses.include?(s)) %></li>
13 19 <% end -%>
14 20 </ul>
15 21 </li>
16 <% else %>
17 <li><%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id)},
18 :class => 'icon-edit', :disabled => !@can[:edit] %></li>
19 <% end %>
22 <% end %>
20 23
21 24 <% unless @trackers.nil? %>
22 25 <li class="folder">
23 26 <a href="#" class="submenu"><%= l(:field_tracker) %></a>
24 27 <ul>
25 28 <% @trackers.each do |t| -%>
26 29 <li><%= context_menu_link t.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {'tracker_id' => t}, :back_url => @back}, :method => :post,
27 30 :selected => (@issue && t == @issue.tracker), :disabled => !@can[:edit] %></li>
28 31 <% end -%>
29 32 </ul>
30 33 </li>
31 34 <% end %>
32 35 <li class="folder">
33 36 <a href="#" class="submenu"><%= l(:field_priority) %></a>
34 37 <ul>
35 38 <% @priorities.each do |p| -%>
36 39 <li><%= context_menu_link p.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {'priority_id' => p}, :back_url => @back}, :method => :post,
37 40 :selected => (@issue && p == @issue.priority), :disabled => (!@can[:edit] || @issues.detect {|i| !i.leaf?}) %></li>
38 41 <% end -%>
39 42 </ul>
40 43 </li>
41 44 <% unless @project.nil? || @project.shared_versions.open.empty? -%>
42 45 <li class="folder">
43 46 <a href="#" class="submenu"><%= l(:field_fixed_version) %></a>
44 47 <ul>
45 48 <% @project.shared_versions.open.sort.each do |v| -%>
46 49 <li><%= context_menu_link format_version_name(v), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {'fixed_version_id' => v}, :back_url => @back}, :method => :post,
47 50 :selected => (@issue && v == @issue.fixed_version), :disabled => !@can[:update] %></li>
48 51 <% end -%>
49 52 <li><%= context_menu_link l(:label_none), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {'fixed_version_id' => 'none'}, :back_url => @back}, :method => :post,
50 53 :selected => (@issue && @issue.fixed_version.nil?), :disabled => !@can[:update] %></li>
51 54 </ul>
52 55 </li>
53 56 <% end %>
54 57 <% unless @assignables.nil? || @assignables.empty? -%>
55 58 <li class="folder">
56 59 <a href="#" class="submenu"><%= l(:field_assigned_to) %></a>
57 60 <ul>
58 61 <% @assignables.each do |u| -%>
59 62 <li><%= context_menu_link u.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {'assigned_to_id' => u}, :back_url => @back}, :method => :post,
60 63 :selected => (@issue && u == @issue.assigned_to), :disabled => !@can[:update] %></li>
61 64 <% end -%>
62 65 <li><%= context_menu_link l(:label_nobody), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {'assigned_to_id' => 'none'}, :back_url => @back}, :method => :post,
63 66 :selected => (@issue && @issue.assigned_to.nil?), :disabled => !@can[:update] %></li>
64 67 </ul>
65 68 </li>
66 69 <% end %>
67 70 <% unless @project.nil? || @project.issue_categories.empty? -%>
68 71 <li class="folder">
69 72 <a href="#" class="submenu"><%= l(:field_category) %></a>
70 73 <ul>
71 74 <% @project.issue_categories.each do |u| -%>
72 75 <li><%= context_menu_link u.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {'category_id' => u}, :back_url => @back}, :method => :post,
73 76 :selected => (@issue && u == @issue.category), :disabled => !@can[:update] %></li>
74 77 <% end -%>
75 78 <li><%= context_menu_link l(:label_none), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {'category_id' => 'none'}, :back_url => @back}, :method => :post,
76 79 :selected => (@issue && @issue.category.nil?), :disabled => !@can[:update] %></li>
77 80 </ul>
78 81 </li>
79 82 <% end -%>
80 83 <% if Issue.use_field_for_done_ratio? %>
81 84 <li class="folder">
82 85 <a href="#" class="submenu"><%= l(:field_done_ratio) %></a>
83 86 <ul>
84 87 <% (0..10).map{|x|x*10}.each do |p| -%>
85 88 <li><%= context_menu_link "#{p}%", {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), :issue => {'done_ratio' => p}, :back_url => @back}, :method => :post,
86 89 :selected => (@issue && p == @issue.done_ratio), :disabled => (!@can[:edit] || @issues.detect {|i| !i.leaf?}) %></li>
87 90 <% end -%>
88 91 </ul>
89 92 </li>
90 93 <% end %>
91 94 <% if !@issue.nil? %>
92 95 <% if @can[:log_time] -%>
93 96 <li><%= context_menu_link l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue},
94 97 :class => 'icon-time-add' %></li>
95 98 <% end %>
96 99 <% if User.current.logged? %>
97 100 <li><%= watcher_link(@issue, User.current) %></li>
98 101 <% end %>
99 102 <% end %>
100 103
101 104 <% if @issue.present? %>
102 105 <li><%= context_menu_link l(:button_duplicate), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue},
103 106 :class => 'icon-duplicate', :disabled => !@can[:copy] %></li>
104 107 <% end %>
105 108 <li><%= context_menu_link l(:button_copy), new_issue_move_path(:ids => @issues.collect(&:id), :copy_options => {:copy => 't'}),
106 109 :class => 'icon-copy', :disabled => !@can[:move] %></li>
107 110 <li><%= context_menu_link l(:button_move), new_issue_move_path(:ids => @issues.collect(&:id)),
108 111 :class => 'icon-move', :disabled => !@can[:move] %></li>
109 112 <li><%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :ids => @issues.collect(&:id)},
110 113 :method => :post, :confirm => l(:text_issues_destroy_confirmation), :class => 'icon-del', :disabled => !@can[:delete] %></li>
111 114
112 115 <%= call_hook(:view_issues_context_menu_end, {:issues => @issues, :can => @can, :back => @back }) %>
113 116 </ul>
@@ -1,89 +1,92
1 1 require File.dirname(__FILE__) + '/../test_helper'
2 2
3 3 class ContextMenusControllerTest < ActionController::TestCase
4 4 fixtures :all
5 5
6 6 def test_context_menu_one_issue
7 7 @request.session[:user_id] = 2
8 8 get :issues, :ids => [1]
9 9 assert_response :success
10 10 assert_template 'context_menu'
11 11 assert_tag :tag => 'a', :content => 'Edit',
12 12 :attributes => { :href => '/issues/1/edit',
13 13 :class => 'icon-edit' }
14 14 assert_tag :tag => 'a', :content => 'Closed',
15 :attributes => { :href => '/issues/1?issue%5Bstatus_id%5D=5',
15 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bstatus_id%5D=5',
16 16 :class => '' }
17 17 assert_tag :tag => 'a', :content => 'Immediate',
18 18 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bpriority_id%5D=8',
19 19 :class => '' }
20 20 # Versions
21 21 assert_tag :tag => 'a', :content => '2.0',
22 22 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=3',
23 23 :class => '' }
24 24 assert_tag :tag => 'a', :content => 'eCookbook Subproject 1 - 2.0',
25 25 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=4',
26 26 :class => '' }
27 27
28 28 assert_tag :tag => 'a', :content => 'Dave Lopper',
29 29 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bassigned_to_id%5D=3',
30 30 :class => '' }
31 31 assert_tag :tag => 'a', :content => 'Duplicate',
32 32 :attributes => { :href => '/projects/ecookbook/issues/1/copy',
33 33 :class => 'icon-duplicate' }
34 34 assert_tag :tag => 'a', :content => 'Copy',
35 35 :attributes => { :href => '/issues/move/new?copy_options%5Bcopy%5D=t&amp;ids%5B%5D=1',
36 36 :class => 'icon-copy' }
37 37 assert_tag :tag => 'a', :content => 'Move',
38 38 :attributes => { :href => '/issues/move/new?ids%5B%5D=1',
39 39 :class => 'icon-move' }
40 40 assert_tag :tag => 'a', :content => 'Delete',
41 41 :attributes => { :href => '/issues/destroy?ids%5B%5D=1',
42 42 :class => 'icon-del' }
43 43 end
44 44
45 45 def test_context_menu_one_issue_by_anonymous
46 46 get :issues, :ids => [1]
47 47 assert_response :success
48 48 assert_template 'context_menu'
49 49 assert_tag :tag => 'a', :content => 'Delete',
50 50 :attributes => { :href => '#',
51 51 :class => 'icon-del disabled' }
52 52 end
53 53
54 54 def test_context_menu_multiple_issues_of_same_project
55 55 @request.session[:user_id] = 2
56 56 get :issues, :ids => [1, 2]
57 57 assert_response :success
58 58 assert_template 'context_menu'
59 59 assert_tag :tag => 'a', :content => 'Edit',
60 60 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2',
61 61 :class => 'icon-edit' }
62 assert_tag :tag => 'a', :content => 'Closed',
63 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bstatus_id%5D=5',
64 :class => '' }
62 65 assert_tag :tag => 'a', :content => 'Immediate',
63 66 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bpriority_id%5D=8',
64 67 :class => '' }
65 68 assert_tag :tag => 'a', :content => 'Dave Lopper',
66 69 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bassigned_to_id%5D=3',
67 70 :class => '' }
68 71 assert_tag :tag => 'a', :content => 'Copy',
69 72 :attributes => { :href => '/issues/move/new?copy_options%5Bcopy%5D=t&amp;ids%5B%5D=1&amp;ids%5B%5D=2',
70 73 :class => 'icon-copy' }
71 74 assert_tag :tag => 'a', :content => 'Move',
72 75 :attributes => { :href => '/issues/move/new?ids%5B%5D=1&amp;ids%5B%5D=2',
73 76 :class => 'icon-move' }
74 77 assert_tag :tag => 'a', :content => 'Delete',
75 78 :attributes => { :href => '/issues/destroy?ids%5B%5D=1&amp;ids%5B%5D=2',
76 79 :class => 'icon-del' }
77 80 end
78 81
79 82 def test_context_menu_multiple_issues_of_different_project
80 83 @request.session[:user_id] = 2
81 84 get :issues, :ids => [1, 2, 4]
82 85 assert_response :success
83 86 assert_template 'context_menu'
84 87 assert_tag :tag => 'a', :content => 'Delete',
85 88 :attributes => { :href => '#',
86 89 :class => 'icon-del disabled' }
87 90 end
88 91
89 92 end
General Comments 0
You need to be logged in to leave comments. Login now