diff --git a/app/views/messages/show.html.erb b/app/views/messages/show.html.erb index b8abf0321..6c902d087 100644 --- a/app/views/messages/show.html.erb +++ b/app/views/messages/show.html.erb @@ -90,3 +90,11 @@ <% end %> <% html_title @topic.subject %> +<% content_for :sidebar do %> + <% if User.current.allowed_to?(:add_message_watchers, @project) || + (@topic.watchers.present? && User.current.allowed_to?(:view_message_watchers, @project)) %> +
+ <%= render :partial => 'watchers/watchers', :locals => {:watched => @topic} %> +
+ <% end %> +<% end %> diff --git a/app/views/watchers/_new.html.erb b/app/views/watchers/_new.html.erb index f313d04d3..bc08a3322 100644 --- a/app/views/watchers/_new.html.erb +++ b/app/views/watchers/_new.html.erb @@ -1,4 +1,12 @@ -

<%= l(:permission_add_issue_watchers) %>

+<% +title = + if watchables.present? + l(:"permission_add_#{watchables.first.class.name.underscore}_watchers") + else + l(:permission_add_issue_watchers) + end +-%> +

<%= title %>

<%= form_tag(watchables.present? ? watchers_path : watchers_append_path, :remote => true, diff --git a/app/views/watchers/_watchers.html.erb b/app/views/watchers/_watchers.html.erb index 248966282..b53e09d50 100644 --- a/app/views/watchers/_watchers.html.erb +++ b/app/views/watchers/_watchers.html.erb @@ -1,12 +1,13 @@ -<% if User.current.allowed_to?(:add_issue_watchers, watched.project) %> +<% watched_klass_name = watched.class.name.underscore -%> +<% if User.current.allowed_to?(:"add_#{watched_klass_name}_watchers", watched.project) %>
<%= link_to l(:button_add), - new_watchers_path(:object_type => watched.class.name.underscore, :object_id => watched), + new_watchers_path(:object_type => watched_klass_name, :object_id => watched), :remote => true, :method => 'get' %>
<% end %> -

<%= l(:label_issue_watchers) %> (<%= watched.watcher_users.size %>)

+

<%= l(:"label_#{watched_klass_name}_watchers") %> (<%= watched.watcher_users.size %>)

<%= watchers_list(watched) %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 00f246f33..7b4b6debb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -569,6 +569,9 @@ en: permission_edit_own_messages: Edit own messages permission_delete_messages: Delete messages permission_delete_own_messages: Delete own messages + permission_view_message_watchers: View message watchers list + permission_add_message_watchers: Add message watchers + permission_delete_message_watchers: Delete message watchers permission_export_wiki_pages: Export wiki pages permission_manage_subtasks: Manage subtasks permission_manage_related_issues: Manage related issues @@ -952,6 +955,7 @@ en: label_incoming_emails: Incoming emails label_generate_key: Generate a key label_issue_watchers: Watchers + label_message_watchers: Watchers label_example: Example label_display: Display label_sort: Sort diff --git a/lib/redmine.rb b/lib/redmine.rb index 409da528a..7e45db853 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -188,6 +188,9 @@ Redmine::AccessControl.map do |map| map.permission :edit_own_messages, {:messages => :edit, :attachments => :upload}, :require => :loggedin map.permission :delete_messages, {:messages => :destroy}, :require => :member map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin + map.permission :view_message_watchers, {}, :read => true + map.permission :add_message_watchers, {:watchers => [:new, :create, :autocomplete_for_user]} + map.permission :delete_message_watchers, {:watchers => :destroy} map.permission :manage_boards, {:projects => :settings, :boards => [:new, :create, :edit, :update, :destroy]}, :require => :member end diff --git a/test/fixtures/roles.yml b/test/fixtures/roles.yml index 650511e2d..61c324b1e 100644 --- a/test/fixtures/roles.yml +++ b/test/fixtures/roles.yml @@ -58,6 +58,9 @@ roles_001: - :add_messages - :edit_messages - :delete_messages + - :view_message_watchers + - :add_message_watchers + - :delete_message_watchers - :manage_boards - :view_files - :manage_files @@ -113,6 +116,7 @@ roles_002: - :add_messages - :edit_own_messages - :delete_own_messages + - :view_message_watchers - :manage_boards - :view_files - :manage_files @@ -156,6 +160,7 @@ roles_003: - :delete_wiki_pages - :view_messages - :add_messages + - :view_message_watchers - :manage_boards - :view_files - :manage_files diff --git a/test/functional/messages_controller_test.rb b/test/functional/messages_controller_test.rb index 44b880f9b..b42c891a5 100644 --- a/test/functional/messages_controller_test.rb +++ b/test/functional/messages_controller_test.rb @@ -20,7 +20,8 @@ require File.expand_path('../../test_helper', __FILE__) class MessagesControllerTest < Redmine::ControllerTest - fixtures :projects, :users, :email_addresses, :user_preferences, :members, :member_roles, :roles, :boards, :messages, :enabled_modules + fixtures :projects, :users, :email_addresses, :user_preferences, :members, :member_roles, :roles, :boards, :messages, :enabled_modules, + :watchers def setup User.current = nil @@ -88,6 +89,31 @@ class MessagesControllerTest < Redmine::ControllerTest assert_response 404 end + def test_show_should_display_watchers + @request.session[:user_id] = 2 + message = Message.find(1) + message.add_watcher User.find(2) + message.add_watcher Group.find(10) + [['1', true], ['0', false]].each do |(gravatar_enabled, is_display_gravatar)| + with_settings :gravatar_enabled => gravatar_enabled do + get(:show, :params => {:board_id => 1, :id => 1}) + end + + assert_select 'div#watchers ul' do + assert_select 'li.user-2' do + assert_select 'img.gravatar[title=?]', 'John Smith', is_display_gravatar + assert_select 'a[href="/users/2"]' + assert_select 'a[class*=delete]' + end + assert_select "li.user-10" do + assert_select 'img.gravatar[title=?]', 'A Team', is_display_gravatar + assert_select 'a[href="/users/10"]', false + assert_select 'a[class*=delete]' + end + end + end + end + def test_get_new @request.session[:user_id] = 2 get(:new, :params => {:board_id => 1}) diff --git a/test/functional/watchers_controller_test.rb b/test/functional/watchers_controller_test.rb index 4e93ce606..3690a77bf 100644 --- a/test/functional/watchers_controller_test.rb +++ b/test/functional/watchers_controller_test.rb @@ -21,7 +21,8 @@ require File.expand_path('../../test_helper', __FILE__) class WatchersControllerTest < Redmine::ControllerTest fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, - :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers + :issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers, + :boards, :messages def setup User.current = nil @@ -155,6 +156,13 @@ class WatchersControllerTest < Redmine::ControllerTest assert_match /ajax-modal/, response.body end + def test_new_for_message + @request.session[:user_id] = 2 + get :new, :params => {:object_type => 'message', :object_id => '1'}, :xhr => true + assert_response :success + assert_match /ajax-modal/, response.body + end + def test_new_with_multiple_objects @request.session[:user_id] = 2 get :new, :params => {:object_type => 'issue', :object_id => ['1', '2']}, :xhr => true @@ -216,6 +224,20 @@ class WatchersControllerTest < Redmine::ControllerTest assert Issue.find(2).watched_by?(User.find(4)) end + def test_create_for_message + @request.session[:user_id] = 2 + assert_difference('Watcher.count') do + post :create, :params => { + :object_type => 'message', :object_id => '1', + :watcher => {:user_id => '4'} + }, :xhr => true + assert_response :success + assert_match /watchers/, response.body + assert_match /ajax-modal/, response.body + end + assert Message.find(1).watched_by?(User.find(4)) + end + def test_create_with_mutiple_users @request.session[:user_id] = 2 assert_difference('Watcher.count', 3) do @@ -233,6 +255,23 @@ class WatchersControllerTest < Redmine::ControllerTest assert issue.watched_by?(Group.find(10)) end + def test_create_for_message_with_mutiple_users + @request.session[:user_id] = 2 + assert_difference('Watcher.count', 3) do + post :create, :params => { + :object_type => 'message', :object_id => '1', + :watcher => {:user_ids => ['4', '7', '10']} + }, :xhr => true + assert_response :success + assert_match /watchers/, response.body + assert_match /ajax-modal/, response.body + end + message = Message.find(1) + assert message.watched_by?(User.find(4)) + assert message.watched_by?(User.find(7)) + assert message.watched_by?(Group.find(10)) + end + def test_create_with_mutiple_objects @request.session[:user_id] = 2 assert_difference('Watcher.count', 6) do @@ -409,6 +448,22 @@ class WatchersControllerTest < Redmine::ControllerTest assert !Issue.find(2).watched_by?(User.find(3)) end + def test_destroy_for_meessage + @request.session[:user_id] = 2 + message = Message.find(1) + user = User.find(1) + assert message.watched_by?(user) + assert_difference('Watcher.count', -1) do + delete :destroy, :params => { + :object_type => 'message', :object_id => '1', :user_id => '1' + }, :xhr => true + assert_response :success + assert_match /watchers/, response.body + end + message.reload + assert !message.watched_by?(user) + end + def test_destroy_locked_user user = User.find(3) user.lock!