##// END OF EJS Templates
Bulk-edit custom fields through context menu (#6296)....
Jean-Philippe Lang -
r8704:5e0c1cc5ce9e
parent child
Show More
@@ -42,6 +42,19 class ContextMenusController < ApplicationController
42 @statuses = IssueStatus.find(:all, :order => 'position')
42 @statuses = IssueStatus.find(:all, :order => 'position')
43 @back = back_url
43 @back = back_url
44
44
45 @options_by_custom_field = {}
46 if @can[:edit]
47 custom_fields = @issues.map(&:available_custom_fields).inject {|memo, f| memo & f}.select do |f|
48 %w(bool list user version).include?(f.field_format) && !f.multiple?
49 end
50 custom_fields.each do |field|
51 values = field.possible_values_options(@projects)
52 if values.any?
53 @options_by_custom_field[field] = values
54 end
55 end
56 end
57
45 render :layout => false
58 render :layout => false
46 end
59 end
47
60
@@ -33,4 +33,11 module ContextMenusHelper
33 end
33 end
34 link_to h(name), url, options
34 link_to h(name), url, options
35 end
35 end
36
37 def bulk_update_custom_field_context_menu_link(field, text, value)
38 context_menu_link h(text),
39 {:controller => 'issues', :action => 'bulk_update', :ids => @issues.collect(&:id), :issue => {'custom_field_values' => {field.id => value}}, :back_url => @back},
40 :method => :post,
41 :selected => (@issue && @issue.custom_field_value(field) == value)
42 end
36 end
43 end
@@ -77,8 +77,10 class CustomField < ActiveRecord::Base
77 else
77 else
78 []
78 []
79 end
79 end
80 when 'bool'
81 [[l(:general_text_Yes), '1'], [l(:general_text_No), '0']]
80 else
82 else
81 read_attribute :possible_values
83 read_attribute(:possible_values) || []
82 end
84 end
83 end
85 end
84
86
@@ -86,6 +88,8 class CustomField < ActiveRecord::Base
86 case field_format
88 case field_format
87 when 'user', 'version'
89 when 'user', 'version'
88 possible_values_options(obj).collect(&:last)
90 possible_values_options(obj).collect(&:last)
91 when 'bool'
92 ['1', '0']
89 else
93 else
90 read_attribute :possible_values
94 read_attribute :possible_values
91 end
95 end
@@ -100,6 +100,20
100 </li>
100 </li>
101 <% end %>
101 <% end %>
102
102
103 <% @options_by_custom_field.each do |field, options| %>
104 <li class="folder">
105 <a href="#" class="submenu"><%= h(field.name) %></a>
106 <ul>
107 <% options.each do |text, value| %>
108 <li><%= bulk_update_custom_field_context_menu_link(field, text, value || text) %></li>
109 <% end %>
110 <% unless field.is_required? %>
111 <li><%= bulk_update_custom_field_context_menu_link(field, l(:label_none), '') %></li>
112 <% end %>
113 </ul>
114 </li>
115 <% end %>
116
103 <% if !@issue.nil? %>
117 <% if !@issue.nil? %>
104 <% if @can[:log_time] -%>
118 <% if @can[:log_time] -%>
105 <li><%= context_menu_link l(:button_log_time), {:controller => 'timelog', :action => 'new', :issue_id => @issue},
119 <li><%= context_menu_link l(:button_log_time), {:controller => 'timelog', :action => 'new', :issue_id => @issue},
@@ -39,7 +39,7
39 }
39 }
40 #context-menu li>a { width:auto; } /* others */
40 #context-menu li>a { width:auto; } /* others */
41 #context-menu a.disabled, #context-menu a.disabled:hover {color: #ccc;}
41 #context-menu a.disabled, #context-menu a.disabled:hover {color: #ccc;}
42 #context-menu li a.submenu { background:url("../images/bullet_arrow_right.png") right no-repeat; }
42 #context-menu li a.submenu { padding-right:16px; background:url("../images/bullet_arrow_right.png") right no-repeat; }
43 #context-menu li:hover { border:1px solid gray; background-color:#eee; }
43 #context-menu li:hover { border:1px solid gray; background-color:#eee; }
44 #context-menu a:hover {color:#2A5685;}
44 #context-menu a:hover {color:#2A5685;}
45 #context-menu li.folder:hover { z-index:40; }
45 #context-menu li.folder:hover { z-index:40; }
@@ -117,6 +117,102 class ContextMenusControllerTest < ActionController::TestCase
117 :class => 'icon-del' }
117 :class => 'icon-del' }
118 end
118 end
119
119
120 def test_context_menu_should_include_list_custom_fields
121 field = IssueCustomField.create!(:name => 'List', :field_format => 'list',
122 :possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
123 @request.session[:user_id] = 2
124 get :issues, :ids => [1, 2]
125
126 assert_tag 'a',
127 :content => 'List',
128 :attributes => {:href => '#'},
129 :sibling => {:tag => 'ul', :children => {:count => 3}}
130
131 assert_tag 'a',
132 :content => 'Foo',
133 :attributes => {:href => "/issues/bulk_update?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=Foo"}
134 assert_tag 'a',
135 :content => 'none',
136 :attributes => {:href => "/issues/bulk_update?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D="}
137 end
138
139 def test_context_menu_should_not_include_null_value_for_required_custom_fields
140 field = IssueCustomField.create!(:name => 'List', :is_required => true, :field_format => 'list',
141 :possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
142 @request.session[:user_id] = 2
143 get :issues, :ids => [1, 2]
144
145 assert_tag 'a',
146 :content => 'List',
147 :attributes => {:href => '#'},
148 :sibling => {:tag => 'ul', :children => {:count => 2}}
149 end
150
151 def test_context_menu_on_single_issue_should_select_current_custom_field_value
152 field = IssueCustomField.create!(:name => 'List', :field_format => 'list',
153 :possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
154 issue = Issue.find(1)
155 issue.custom_field_values = {field.id => 'Bar'}
156 issue.save!
157 @request.session[:user_id] = 2
158 get :issues, :ids => [1]
159
160 assert_tag 'a',
161 :content => 'List',
162 :attributes => {:href => '#'},
163 :sibling => {:tag => 'ul', :children => {:count => 3}}
164 assert_tag 'a',
165 :content => 'Bar',
166 :attributes => {:class => /icon-checked/}
167 end
168
169 def test_context_menu_should_include_bool_custom_fields
170 field = IssueCustomField.create!(:name => 'Bool', :field_format => 'bool',
171 :is_for_all => true, :tracker_ids => [1, 2, 3])
172 @request.session[:user_id] = 2
173 get :issues, :ids => [1, 2]
174
175 assert_tag 'a',
176 :content => 'Bool',
177 :attributes => {:href => '#'},
178 :sibling => {:tag => 'ul', :children => {:count => 3}}
179
180 assert_tag 'a',
181 :content => 'Yes',
182 :attributes => {:href => "/issues/bulk_update?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=1"}
183 end
184
185 def test_context_menu_should_include_user_custom_fields
186 field = IssueCustomField.create!(:name => 'User', :field_format => 'user',
187 :is_for_all => true, :tracker_ids => [1, 2, 3])
188 @request.session[:user_id] = 2
189 get :issues, :ids => [1, 2]
190
191 assert_tag 'a',
192 :content => 'User',
193 :attributes => {:href => '#'},
194 :sibling => {:tag => 'ul', :children => {:count => Project.find(1).members.count + 1}}
195
196 assert_tag 'a',
197 :content => 'John Smith',
198 :attributes => {:href => "/issues/bulk_update?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=2"}
199 end
200
201 def test_context_menu_should_include_version_custom_fields
202 field = IssueCustomField.create!(:name => 'Version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1, 2, 3])
203 @request.session[:user_id] = 2
204 get :issues, :ids => [1, 2]
205
206 assert_tag 'a',
207 :content => 'Version',
208 :attributes => {:href => '#'},
209 :sibling => {:tag => 'ul', :children => {:count => Project.find(1).shared_versions.count + 1}}
210
211 assert_tag 'a',
212 :content => '2.0',
213 :attributes => {:href => "/issues/bulk_update?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=3"}
214 end
215
120 def test_context_menu_by_assignable_user_should_include_assigned_to_me_link
216 def test_context_menu_by_assignable_user_should_include_assigned_to_me_link
121 @request.session[:user_id] = 2
217 @request.session[:user_id] = 2
122 get :issues, :ids => [1]
218 get :issues, :ids => [1]
General Comments 0
You need to be logged in to leave comments. Login now