mirror of
https://github.com/meineerde/redmine.git
synced 2025-12-20 07:21:12 +00:00
Allow addition of watchers via bulk edit context menu (#5754).
git-svn-id: http://svn.redmine.org/redmine/trunk@15311 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
c8c694840d
commit
5adc1ddde9
@ -32,6 +32,7 @@ class ContextMenusController < ApplicationController
|
|||||||
@can = {:edit => User.current.allowed_to?(:edit_issues, @projects),
|
@can = {:edit => User.current.allowed_to?(:edit_issues, @projects),
|
||||||
:log_time => (@project && User.current.allowed_to?(:log_time, @project)),
|
:log_time => (@project && User.current.allowed_to?(:log_time, @project)),
|
||||||
:copy => User.current.allowed_to?(:copy_issues, @projects) && Issue.allowed_target_projects.any?,
|
: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)
|
:delete => User.current.allowed_to?(:delete_issues, @projects)
|
||||||
}
|
}
|
||||||
if @project
|
if @project
|
||||||
|
|||||||
@ -42,7 +42,9 @@ class WatchersController < ApplicationController
|
|||||||
end
|
end
|
||||||
users = User.active.visible.where(:id => user_ids.flatten.compact.uniq)
|
users = User.active.visible.where(:id => user_ids.flatten.compact.uniq)
|
||||||
users.each do |user|
|
users.each do |user|
|
||||||
Watcher.create(:watchable => @watched, :user => user)
|
@watchables.each do |watchable|
|
||||||
|
Watcher.create(:watchable => watchable, :user => user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to_referer_or {render :text => 'Watcher added.', :layout => true}}
|
format.html { redirect_to_referer_or {render :text => 'Watcher added.', :layout => true}}
|
||||||
@ -62,7 +64,10 @@ class WatchersController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
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|
|
respond_to do |format|
|
||||||
format.html { redirect_to :back }
|
format.html { redirect_to :back }
|
||||||
format.js
|
format.js
|
||||||
@ -81,30 +86,21 @@ class WatchersController < ApplicationController
|
|||||||
|
|
||||||
def find_project
|
def find_project
|
||||||
if params[:object_type] && params[:object_id]
|
if params[:object_type] && params[:object_id]
|
||||||
klass = Object.const_get(params[:object_type].camelcase)
|
@watchables = find_objets_from_params
|
||||||
return false unless klass.respond_to?('watched_by')
|
@projects = @watchables.map(&:project).uniq
|
||||||
@watched = klass.find(params[:object_id])
|
if @projects.size == 1
|
||||||
@project = @watched.project
|
@project = @projects.first
|
||||||
|
end
|
||||||
elsif params[:project_id]
|
elsif params[:project_id]
|
||||||
@project = Project.visible.find_by_param(params[:project_id])
|
@project = Project.visible.find_by_param(params[:project_id])
|
||||||
end
|
end
|
||||||
rescue
|
|
||||||
render_404
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_watchables
|
def find_watchables
|
||||||
klass = Object.const_get(params[:object_type].camelcase) rescue nil
|
@watchables = find_objets_from_params
|
||||||
if klass && klass.respond_to?('watched_by')
|
unless @watchables.present?
|
||||||
@watchables = klass.where(:id => Array.wrap(params[:object_id])).to_a
|
render_404
|
||||||
raise Unauthorized if @watchables.any? {|w|
|
|
||||||
if w.respond_to?(:visible?)
|
|
||||||
!w.visible?
|
|
||||||
elsif w.respond_to?(:project) && w.project
|
|
||||||
!w.project.visible?
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
render_404 unless @watchables.present?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_watcher(watchables, user, watching)
|
def set_watcher(watchables, user, watching)
|
||||||
@ -125,9 +121,24 @@ class WatchersController < ApplicationController
|
|||||||
scope = User.all.limit(100)
|
scope = User.all.limit(100)
|
||||||
end
|
end
|
||||||
users = scope.active.visible.sorted.like(params[:q]).to_a
|
users = scope.active.visible.sorted.like(params[:q]).to_a
|
||||||
if @watched
|
if @watchables
|
||||||
users -= @watched.watcher_users
|
users -= @watchables.map(&:watcher_users).flatten
|
||||||
end
|
end
|
||||||
users
|
users
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
@ -117,6 +117,18 @@
|
|||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% 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? %>
|
<% if User.current.logged? %>
|
||||||
<li><%= watcher_link(@issues, User.current) %></li>
|
<li><%= watcher_link(@issues, User.current) %></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@ -1,19 +1,23 @@
|
|||||||
<h3 class="title"><%= l(:permission_add_issue_watchers) %></h3>
|
<h3 class="title"><%= l(:permission_add_issue_watchers) %></h3>
|
||||||
|
|
||||||
<%= form_tag({:controller => 'watchers',
|
<%= form_tag(watchables.present? ? watchers_path : watchers_append_path,
|
||||||
:action => (watched ? 'create' : 'append'),
|
|
||||||
:object_type => (watched && watched.class.name.underscore),
|
|
||||||
:object_id => watched,
|
|
||||||
:project_id => @project},
|
|
||||||
:remote => true,
|
:remote => true,
|
||||||
:method => :post,
|
:method => :post,
|
||||||
:id => 'new-watcher-form') do %>
|
: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>
|
<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',
|
<%= javascript_tag "observeSearchfield('user_search', 'users_for_watcher', '#{ escape_javascript url_for(:controller => 'watchers',
|
||||||
:action => 'autocomplete_for_user',
|
:action => 'autocomplete_for_user',
|
||||||
:object_type => (watched && watched.class.name.underscore),
|
:object_type => (watchables.present? ? watchables.first.class.name.underscore : nil),
|
||||||
:object_id => watched,
|
:object_id => (watchables.present? && watchables.size == 1 ? watchables.first.id : nil),
|
||||||
:project_id => @project) }')" %>
|
:project_id => @project) }')" %>
|
||||||
|
|
||||||
<div id="users_for_watcher">
|
<div id="users_for_watcher">
|
||||||
|
|||||||
@ -1,2 +1,5 @@
|
|||||||
$('#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})) %>');
|
||||||
$('#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 +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');
|
showModal('ajax-modal', '400px');
|
||||||
$('#ajax-modal').addClass('new-watcher');
|
$('#ajax-modal').addClass('new-watcher');
|
||||||
|
|||||||
@ -91,7 +91,7 @@ Rails.application.routes.draw do
|
|||||||
|
|
||||||
post 'watchers/watch', :to => 'watchers#watch', :as => 'watch'
|
post 'watchers/watch', :to => 'watchers#watch', :as => 'watch'
|
||||||
delete 'watchers/watch', :to => 'watchers#unwatch'
|
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', :to => 'watchers#create'
|
||||||
post 'watchers/append', :to => 'watchers#append'
|
post 'watchers/append', :to => 'watchers#append'
|
||||||
delete 'watchers', :to => 'watchers#destroy'
|
delete 'watchers', :to => 'watchers#destroy'
|
||||||
|
|||||||
@ -67,7 +67,7 @@ function contextMenuClick(event) {
|
|||||||
// click is outside the rows
|
// click is outside the rows
|
||||||
if (target.is('a') && (target.hasClass('disabled') || target.hasClass('submenu'))) {
|
if (target.is('a') && (target.hasClass('disabled') || target.hasClass('submenu'))) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
} else if (target.is('.toggle-selection')) {
|
} else if (target.is('.toggle-selection') || target.is('.ui-dialog *') || $('#ajax-modal').is(':visible')) {
|
||||||
// nop
|
// nop
|
||||||
} else {
|
} else {
|
||||||
contextMenuUnselectAll();
|
contextMenuUnselectAll();
|
||||||
|
|||||||
@ -133,6 +133,13 @@ class WatchersControllerTest < ActionController::TestCase
|
|||||||
assert_match /ajax-modal/, response.body
|
assert_match /ajax-modal/, response.body
|
||||||
end
|
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
|
def test_new_for_new_record_with_project_id
|
||||||
@request.session[:user_id] = 2
|
@request.session[:user_id] = 2
|
||||||
xhr :get, :new, :project_id => 1
|
xhr :get, :new, :project_id => 1
|
||||||
@ -161,7 +168,7 @@ class WatchersControllerTest < ActionController::TestCase
|
|||||||
assert Issue.find(2).watched_by?(User.find(4))
|
assert Issue.find(2).watched_by?(User.find(4))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_create_multiple
|
def test_create_with_mutiple_users
|
||||||
@request.session[:user_id] = 2
|
@request.session[:user_id] = 2
|
||||||
assert_difference('Watcher.count', 2) do
|
assert_difference('Watcher.count', 2) do
|
||||||
xhr :post, :create, :object_type => 'issue', :object_id => '2',
|
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))
|
assert Issue.find(2).watched_by?(User.find(7))
|
||||||
end
|
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
|
def test_autocomplete_on_watchable_creation
|
||||||
@request.session[:user_id] = 2
|
@request.session[:user_id] = 2
|
||||||
xhr :get, :autocomplete_for_user, :q => 'mi', :project_id => 'ecookbook'
|
xhr :get, :autocomplete_for_user, :q => 'mi', :project_id => 'ecookbook'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user