git-svn-id: http://svn.redmine.org/redmine/trunk@15311 e93f8b46-1217-0410-a6f0-8f06a7374b81tags/3.3.0
@@ -32,6 +32,7 @@ class ContextMenusController < ApplicationController | |||
@can = {:edit => User.current.allowed_to?(:edit_issues, @projects), | |||
:log_time => (@project && User.current.allowed_to?(:log_time, @project)), | |||
:copy => User.current.allowed_to?(:copy_issues, @projects) && Issue.allowed_target_projects.any?, | |||
:add_watchers => User.current.allowed_to?(:add_issue_watchers, @projects), | |||
:delete => User.current.allowed_to?(:delete_issues, @projects) | |||
} | |||
if @project |
@@ -42,7 +42,9 @@ class WatchersController < ApplicationController | |||
end | |||
users = User.active.visible.where(:id => user_ids.flatten.compact.uniq) | |||
users.each do |user| | |||
Watcher.create(:watchable => @watched, :user => user) | |||
@watchables.each do |watchable| | |||
Watcher.create(:watchable => watchable, :user => user) | |||
end | |||
end | |||
respond_to do |format| | |||
format.html { redirect_to_referer_or {render :text => 'Watcher added.', :layout => true}} | |||
@@ -62,7 +64,10 @@ class WatchersController < ApplicationController | |||
end | |||
def destroy | |||
@watched.set_watcher(User.find(params[:user_id]), false) | |||
user = User.find(params[:user_id]) | |||
@watchables.each do |watchable| | |||
watchable.set_watcher(user, false) | |||
end | |||
respond_to do |format| | |||
format.html { redirect_to :back } | |||
format.js | |||
@@ -81,30 +86,21 @@ class WatchersController < ApplicationController | |||
def find_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 | |||
@watchables = find_objets_from_params | |||
@projects = @watchables.map(&:project).uniq | |||
if @projects.size == 1 | |||
@project = @projects.first | |||
end | |||
elsif params[:project_id] | |||
@project = Project.visible.find_by_param(params[:project_id]) | |||
end | |||
rescue | |||
render_404 | |||
end | |||
def find_watchables | |||
klass = Object.const_get(params[:object_type].camelcase) rescue nil | |||
if klass && klass.respond_to?('watched_by') | |||
@watchables = klass.where(:id => Array.wrap(params[:object_id])).to_a | |||
raise Unauthorized if @watchables.any? {|w| | |||
if w.respond_to?(:visible?) | |||
!w.visible? | |||
elsif w.respond_to?(:project) && w.project | |||
!w.project.visible? | |||
end | |||
} | |||
@watchables = find_objets_from_params | |||
unless @watchables.present? | |||
render_404 | |||
end | |||
render_404 unless @watchables.present? | |||
end | |||
def set_watcher(watchables, user, watching) | |||
@@ -125,9 +121,24 @@ class WatchersController < ApplicationController | |||
scope = User.all.limit(100) | |||
end | |||
users = scope.active.visible.sorted.like(params[:q]).to_a | |||
if @watched | |||
users -= @watched.watcher_users | |||
if @watchables | |||
users -= @watchables.map(&:watcher_users).flatten | |||
end | |||
users | |||
end | |||
def find_objets_from_params | |||
klass = Object.const_get(params[:object_type].camelcase) rescue nil | |||
return unless klass && klass.respond_to?('watched_by') | |||
objects = klass.where(:id => Array.wrap(params[:object_id])).to_a | |||
raise Unauthorized if objects.any? do |w| | |||
if w.respond_to?(:visible?) | |||
!w.visible? | |||
elsif w.respond_to?(:project) && w.project | |||
!w.project.visible? | |||
end | |||
end | |||
objects | |||
end | |||
end |
@@ -117,6 +117,18 @@ | |||
</li> | |||
<% end %> | |||
<% if @can[:add_watchers] %> | |||
<li class="folder"> | |||
<a href="#" class="submenu"><%= l(:label_issue_watchers) %></a> | |||
<ul> | |||
<li><%= context_menu_link l(:button_add), | |||
new_watchers_path(:object_type => 'issue', :object_id => @issue_ids), | |||
:remote => true, | |||
:class => 'icon-add' %></li> | |||
</ul> | |||
</li> | |||
<% end %> | |||
<% if User.current.logged? %> | |||
<li><%= watcher_link(@issues, User.current) %></li> | |||
<% end %> |
@@ -1,19 +1,23 @@ | |||
<h3 class="title"><%= l(:permission_add_issue_watchers) %></h3> | |||
<%= form_tag({:controller => 'watchers', | |||
:action => (watched ? 'create' : 'append'), | |||
:object_type => (watched && watched.class.name.underscore), | |||
:object_id => watched, | |||
:project_id => @project}, | |||
<%= form_tag(watchables.present? ? watchers_path : watchers_append_path, | |||
:remote => true, | |||
:method => :post, | |||
:id => 'new-watcher-form') do %> | |||
<% if watchables.present? %> | |||
<%= hidden_field_tag 'object_type', watchables.first.class.name.underscore %> | |||
<% watchables.each do |watchable| %> | |||
<%= hidden_field_tag 'object_id[]', watchable.id %> | |||
<% end %> | |||
<% end %> | |||
<%= hidden_field_tag 'project_id', @project.id if @project %> | |||
<p><%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %></p> | |||
<%= javascript_tag "observeSearchfield('user_search', 'users_for_watcher', '#{ escape_javascript url_for(:controller => 'watchers', | |||
:action => 'autocomplete_for_user', | |||
:object_type => (watched && watched.class.name.underscore), | |||
:object_id => watched, | |||
:object_type => (watchables.present? ? watchables.first.class.name.underscore : nil), | |||
:object_id => (watchables.present? && watchables.size == 1 ? watchables.first.id : nil), | |||
:project_id => @project) }')" %> | |||
<div id="users_for_watcher"> |
@@ -1,2 +1,5 @@ | |||
$('#ajax-modal').html('<%= escape_javascript(render(:partial => 'watchers/new', :locals => {:watched => @watched, :users => @users})) %>'); | |||
$('#watchers').html('<%= escape_javascript(render(:partial => 'watchers/watchers', :locals => {:watched => @watched})) %>'); | |||
$('#ajax-modal').html('<%= escape_javascript(render(:partial => 'watchers/new', :locals => {:watchables => @watchables, :users => @users})) %>'); | |||
<% if @watchables.size == 1 %> | |||
$('#watchers').html('<%= escape_javascript(render(:partial => 'watchers/watchers', :locals => {:watched => @watchables.first})) %>'); | |||
<% end %> |
@@ -1 +1,3 @@ | |||
$('#watchers').html('<%= escape_javascript(render(:partial => 'watchers/watchers', :locals => {:watched => @watched})) %>'); | |||
<% if @watchables.size == 1 %> | |||
$('#watchers').html('<%= escape_javascript(render(:partial => 'watchers/watchers', :locals => {:watched => @watchables.first})) %>'); | |||
<% end %> |
@@ -1,3 +1,3 @@ | |||
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'watchers/new', :locals => {:watched => @watched, :users => @users}) %>'); | |||
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'watchers/new', :locals => {:watchables => @watchables, :users => @users}) %>'); | |||
showModal('ajax-modal', '400px'); | |||
$('#ajax-modal').addClass('new-watcher'); |
@@ -91,7 +91,7 @@ Rails.application.routes.draw do | |||
post 'watchers/watch', :to => 'watchers#watch', :as => 'watch' | |||
delete 'watchers/watch', :to => 'watchers#unwatch' | |||
get 'watchers/new', :to => 'watchers#new' | |||
get 'watchers/new', :to => 'watchers#new', :as => 'new_watchers' | |||
post 'watchers', :to => 'watchers#create' | |||
post 'watchers/append', :to => 'watchers#append' | |||
delete 'watchers', :to => 'watchers#destroy' |
@@ -67,7 +67,7 @@ function contextMenuClick(event) { | |||
// click is outside the rows | |||
if (target.is('a') && (target.hasClass('disabled') || target.hasClass('submenu'))) { | |||
event.preventDefault(); | |||
} else if (target.is('.toggle-selection')) { | |||
} else if (target.is('.toggle-selection') || target.is('.ui-dialog *') || $('#ajax-modal').is(':visible')) { | |||
// nop | |||
} else { | |||
contextMenuUnselectAll(); |
@@ -133,6 +133,13 @@ class WatchersControllerTest < ActionController::TestCase | |||
assert_match /ajax-modal/, response.body | |||
end | |||
def test_new_with_multiple_objects | |||
@request.session[:user_id] = 2 | |||
xhr :get, :new, :object_type => 'issue', :object_id => ['1', '2'] | |||
assert_response :success | |||
assert_match /ajax-modal/, response.body | |||
end | |||
def test_new_for_new_record_with_project_id | |||
@request.session[:user_id] = 2 | |||
xhr :get, :new, :project_id => 1 | |||
@@ -161,7 +168,7 @@ class WatchersControllerTest < ActionController::TestCase | |||
assert Issue.find(2).watched_by?(User.find(4)) | |||
end | |||
def test_create_multiple | |||
def test_create_with_mutiple_users | |||
@request.session[:user_id] = 2 | |||
assert_difference('Watcher.count', 2) do | |||
xhr :post, :create, :object_type => 'issue', :object_id => '2', | |||
@@ -174,6 +181,21 @@ class WatchersControllerTest < ActionController::TestCase | |||
assert Issue.find(2).watched_by?(User.find(7)) | |||
end | |||
def test_create_with_mutiple_objects | |||
@request.session[:user_id] = 2 | |||
assert_difference('Watcher.count', 4) do | |||
xhr :post, :create, :object_type => 'issue', :object_id => ['1', '2'], | |||
:watcher => {:user_ids => ['4', '7']} | |||
assert_response :success | |||
assert_match /watchers/, response.body | |||
assert_match /ajax-modal/, response.body | |||
end | |||
assert Issue.find(1).watched_by?(User.find(4)) | |||
assert Issue.find(2).watched_by?(User.find(4)) | |||
assert Issue.find(1).watched_by?(User.find(7)) | |||
assert Issue.find(2).watched_by?(User.find(7)) | |||
end | |||
def test_autocomplete_on_watchable_creation | |||
@request.session[:user_id] = 2 | |||
xhr :get, :autocomplete_for_user, :q => 'mi', :project_id => 'ecookbook' |