@priorities = IssuePriority.active
@allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
+ @available_watchers = (@issue.project.users.sort + @issue.watcher_users).uniq
end
def check_for_default_issue_status
render :text => 'Watcher added.', :layout => true
end
+ def append
+ if params[:watcher].is_a?(Hash)
+ user_ids = params[:watcher][:user_ids] || [params[:watcher][:user_id]]
+ users = User.active.find_all_by_id(user_ids)
+ respond_to do |format|
+ format.js do
+ render :update do |page|
+ users.each do |user|
+ page.select("#issue_watcher_user_ids_#{user.id}").each(&:hide)
+ end
+ page.insert_html :bottom, 'watchers_inputs', :text => watchers_checkboxes(nil, users, true)
+ end
+ end
+ end
+ end
+ end
+
def destroy
@watched.set_watcher(User.find(params[:user_id]), false) if request.post?
respond_to do |format|
end
def autocomplete_for_user
- @users = User.active.like(params[:q]).find(:all, :limit => 100) - @watched.watcher_users
+ @users = User.active.like(params[:q]).find(:all, :limit => 100)
+ if @watched
+ @user -= @watched.watcher_users
+ end
render :layout => false
end
private
def find_project
- klass = Object.const_get(params[:object_type].camelcase)
- return false unless klass.respond_to?('watched_by')
- @watched = klass.find(params[:object_id])
- @project = @watched.project
+ if params[:object_type] && params[:object_id]
+ klass = Object.const_get(params[:object_type].camelcase)
+ return false unless klass.respond_to?('watched_by')
+ @watched = klass.find(params[:object_id])
+ @project = @watched.project
+ elsif params[:project_id]
+ @project = Project.visible.find(params[:project_id])
+ end
rescue
render_404
end
end
(lis.empty? ? "" : "<ul>#{ lis.join("\n") }</ul>").html_safe
end
+
+ def watchers_checkboxes(object, users, checked=nil)
+ users.map do |user|
+ c = checked.nil? ? object.watched_by?(user) : checked
+ tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil
+ content_tag 'label', "#{tag} #{h(user)}", :id => "issue_watcher_user_ids_#{user.id}", :class => "floating"
+ end.join
+ end
end
<%= link_to_function(image_tag('delete.png'), 'removeFileField(this)', :title => (l(:button_delete))) %>
</span>
</span>
-<small><%= link_to l(:label_add_another_file), '#', :onclick => 'addFileField(); return false;' %>
-(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
-</small>
+<span class="add_attachment"><%= link_to l(:label_add_another_file), '#', :onclick => 'addFileField(); return false;', :class => 'add_attachment' %>
+(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</span>
<% if @issue.safe_attribute? 'watcher_user_ids' -%>
<p id="watchers_form"><label><%= l(:label_issue_watchers) %></label>
- <% @issue.project.users.sort.each do |user| -%>
- <label class="floating"><%= check_box_tag 'issue[watcher_user_ids][]', user.id, @issue.watched_by?(user), :id => nil %> <%=h user %></label>
- <% end -%>
- </p>
+ <span id="watchers_inputs">
+ <%= watchers_checkboxes(@issue, @available_watchers) %>
+ </span>
+ <span class="search_for_watchers">
+ <%= link_to_remote l(:label_search_for_watchers),
+ :url => {:controller => 'watchers', :action => 'new', :project_id => @issue.project},
+ :method => 'get' %>
+ </span>
+ </p>
<% end %>
</div>
<h3 class="title"><%= l(:permission_add_issue_watchers) %></h3>
<% form_remote_tag :url => {:controller => 'watchers',
- :action => 'create',
+ :action => (watched ? 'create' : 'append'),
:object_type => watched.class.name.underscore,
:object_id => watched},
:method => :post,
:with => 'q') %>
<div id="users_for_watcher">
- <%= principals_check_box_tags 'watcher[user_ids][]', watched.addable_watcher_users %>
+ <%= principals_check_box_tags 'watcher[user_ids][]', (watched ? watched.addable_watcher_users : User.active.all(:limit => 100)) %>
</div>
<p class="buttons">
label_copy_attachments: Copy attachments
label_item_position: "%{position} of %{count}"
label_completed_versions: Completed versions
+ label_search_for_watchers: Search for watchers to add
button_login: Login
button_submit: Submit
:conditions => {:method => :get}
map.connect 'watchers', :controller=> 'watchers', :action => 'create',
:conditions => {:method => :post}
+ map.connect 'watchers/append', :controller=> 'watchers', :action => 'append',
+ :conditions => {:method => :post}
map.connect 'watchers/destroy', :controller=> 'watchers', :action => 'destroy',
:conditions => {:method => :post}
map.connect 'watchers/watch', :controller=> 'watchers', :action => 'watch',
#watchers a.delete:hover {opacity: 1;}
#watchers img.gravatar {margin: 0 4px 2px 0;}
+span#watchers_inputs {overflow:auto; display:block;}
+span.search_for_watchers {display:block;}
+span.search_for_watchers, span.add_attachment {font-size:80%; line-height:2.5em;}
+span.search_for_watchers a, span.add_attachment a {padding-left:16px; background: url(../images/bullet_add.png) no-repeat 0 50%; }
+
+
.highlight { background-color: #FCFD8D;}
.highlight.token-1 { background-color: #faa;}
.highlight.token-2 { background-color: #afa;}
:value => 'Value for field 2'}
end
+ def test_post_create_with_failure_should_preserve_watchers
+ assert !User.find(8).member_of?(Project.find(1))
+
+ @request.session[:user_id] = 2
+ post :create, :project_id => 1,
+ :issue => {:tracker_id => 1,
+ :watcher_user_ids => ['3', '8']}
+ assert_response :success
+ assert_template 'new'
+
+ assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '2', :checked => nil}
+ assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '3', :checked => 'checked'}
+ assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '8', :checked => 'checked'}
+ end
+
def test_post_create_should_ignore_non_safe_attributes
@request.session[:user_id] = 2
assert_nothing_raised do
assert_select_rjs :replace_html, 'ajax-modal'
end
+ def test_new_for_new_record
+ @request.session[:user_id] = 2
+ xhr :get, :new, :project_id => 1
+ assert_response :success
+ assert_select_rjs :replace_html, 'ajax-modal'
+ end
+
def test_create
@request.session[:user_id] = 2
assert_difference('Watcher.count') do
assert Issue.find(2).watched_by?(User.find(7))
end
+ def test_append
+ @request.session[:user_id] = 2
+ assert_no_difference 'Watcher.count' do
+ xhr :post, :append, :watcher => {:user_ids => ['4', '7']}
+ assert_response :success
+ assert_select_rjs :insert_html, 'watchers_inputs' do
+ assert_select 'input[name=?][value=4]', 'issue[watcher_user_ids][]'
+ assert_select 'input[name=?][value=7]', 'issue[watcher_user_ids][]'
+ end
+ end
+ end
+
def test_remove_watcher
@request.session[:user_id] = 2
assert_difference('Watcher.count', -1) do
{ :method => 'get', :path => "/watchers/new" },
{ :controller => 'watchers', :action => 'new' }
)
+ assert_routing(
+ { :method => 'post', :path => "/watchers/append" },
+ { :controller => 'watchers', :action => 'append' }
+ )
assert_routing(
{ :method => 'post', :path => "/watchers" },
{ :controller => 'watchers', :action => 'create' }