Feature #3390 » 3390.patch
| app/views/messages/show.html.erb | ||
|---|---|---|
| 90 | 90 |
<% end %> |
| 91 | 91 | |
| 92 | 92 |
<% html_title @topic.subject %> |
| 93 |
<% content_for :sidebar do %> |
|
| 94 |
<% if User.current.allowed_to?(:add_message_watchers, @project) || |
|
| 95 |
(@topic.watchers.present? && User.current.allowed_to?(:view_message_watchers, @project)) %> |
|
| 96 |
<div id="watchers"> |
|
| 97 |
<%= render :partial => 'watchers/watchers', :locals => {:watched => @topic} %>
|
|
| 98 |
</div> |
|
| 99 |
<% end %> |
|
| 100 |
<% end %> |
|
| app/views/watchers/_new.html.erb | ||
|---|---|---|
| 1 |
<h3 class="title"><%= l(:permission_add_issue_watchers) %></h3> |
|
| 1 |
<% |
|
| 2 |
title = |
|
| 3 |
if watchables.present? |
|
| 4 |
l(:"permission_add_#{watchables.first.class.name.underscore}_watchers")
|
|
| 5 |
else |
|
| 6 |
l(:permission_add_issue_watchers) |
|
| 7 |
end |
|
| 8 |
-%> |
|
| 9 |
<h3 class="title"><%= title %></h3> |
|
| 2 | 10 | |
| 3 | 11 |
<%= form_tag(watchables.present? ? watchers_path : watchers_append_path, |
| 4 | 12 |
:remote => true, |
| app/views/watchers/_watchers.html.erb | ||
|---|---|---|
| 1 |
<% if User.current.allowed_to?(:add_issue_watchers, watched.project) %> |
|
| 1 |
<% watched_klass_name = watched.class.name.underscore -%> |
|
| 2 |
<% if User.current.allowed_to?(:"add_#{watched_klass_name}_watchers", watched.project) %>
|
|
| 2 | 3 |
<div class="contextual"> |
| 3 | 4 |
<%= link_to l(:button_add), |
| 4 |
new_watchers_path(:object_type => watched.class.name.underscore, :object_id => watched),
|
|
| 5 |
new_watchers_path(:object_type => watched_klass_name, :object_id => watched),
|
|
| 5 | 6 |
:remote => true, |
| 6 | 7 |
:method => 'get' %> |
| 7 | 8 |
</div> |
| 8 | 9 |
<% end %> |
| 9 | 10 | |
| 10 |
<h3><%= l(:label_issue_watchers) %> (<%= watched.watcher_users.size %>)</h3>
|
|
| 11 |
<h3><%= l(:"label_#{watched_klass_name}_watchers") %> (<%= watched.watcher_users.size %>)</h3>
|
|
| 11 | 12 | |
| 12 | 13 |
<%= watchers_list(watched) %> |
| config/locales/en.yml | ||
|---|---|---|
| 568 | 568 |
permission_edit_own_messages: Edit own messages |
| 569 | 569 |
permission_delete_messages: Delete messages |
| 570 | 570 |
permission_delete_own_messages: Delete own messages |
| 571 |
permission_view_message_watchers: View watchers list |
|
| 572 |
permission_add_message_watchers: Add watchers |
|
| 573 |
permission_delete_message_watchers: Delete watchers |
|
| 571 | 574 |
permission_export_wiki_pages: Export wiki pages |
| 572 | 575 |
permission_manage_subtasks: Manage subtasks |
| 573 | 576 |
permission_manage_related_issues: Manage related issues |
| ... | ... | |
| 951 | 954 |
label_incoming_emails: Incoming emails |
| 952 | 955 |
label_generate_key: Generate a key |
| 953 | 956 |
label_issue_watchers: Watchers |
| 957 |
label_message_watchers: Watchers |
|
| 954 | 958 |
label_example: Example |
| 955 | 959 |
label_display: Display |
| 956 | 960 |
label_sort: Sort |
| lib/redmine.rb | ||
|---|---|---|
| 188 | 188 |
map.permission :edit_own_messages, {:messages => :edit, :attachments => :upload}, :require => :loggedin
|
| 189 | 189 |
map.permission :delete_messages, {:messages => :destroy}, :require => :member
|
| 190 | 190 |
map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
|
| 191 |
map.permission :view_message_watchers, {}, :read => true
|
|
| 192 |
map.permission :add_message_watchers, {:watchers => [:new, :create, :autocomplete_for_user]}
|
|
| 193 |
map.permission :delete_message_watchers, {:watchers => :destroy}
|
|
| 191 | 194 |
map.permission :manage_boards, {:projects => :settings, :boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
|
| 192 | 195 |
end |
| 193 | 196 | |
| test/fixtures/roles.yml | ||
|---|---|---|
| 58 | 58 |
- :add_messages |
| 59 | 59 |
- :edit_messages |
| 60 | 60 |
- :delete_messages |
| 61 |
- :view_message_watchers |
|
| 62 |
- :add_message_watchers |
|
| 63 |
- :delete_message_watchers |
|
| 61 | 64 |
- :manage_boards |
| 62 | 65 |
- :view_files |
| 63 | 66 |
- :manage_files |
| ... | ... | |
| 113 | 116 |
- :add_messages |
| 114 | 117 |
- :edit_own_messages |
| 115 | 118 |
- :delete_own_messages |
| 119 |
- :view_message_watchers |
|
| 116 | 120 |
- :manage_boards |
| 117 | 121 |
- :view_files |
| 118 | 122 |
- :manage_files |
| ... | ... | |
| 156 | 160 |
- :delete_wiki_pages |
| 157 | 161 |
- :view_messages |
| 158 | 162 |
- :add_messages |
| 163 |
- :view_message_watchers |
|
| 159 | 164 |
- :manage_boards |
| 160 | 165 |
- :view_files |
| 161 | 166 |
- :manage_files |
| test/functional/messages_controller_test.rb | ||
|---|---|---|
| 20 | 20 |
require File.expand_path('../../test_helper', __FILE__)
|
| 21 | 21 | |
| 22 | 22 |
class MessagesControllerTest < Redmine::ControllerTest |
| 23 |
fixtures :projects, :users, :email_addresses, :user_preferences, :members, :member_roles, :roles, :boards, :messages, :enabled_modules |
|
| 23 |
fixtures :projects, :users, :email_addresses, :user_preferences, :members, :member_roles, :roles, :boards, :messages, :enabled_modules, |
|
| 24 |
:watchers |
|
| 24 | 25 | |
| 25 | 26 |
def setup |
| 26 | 27 |
User.current = nil |
| ... | ... | |
| 88 | 89 |
assert_response 404 |
| 89 | 90 |
end |
| 90 | 91 | |
| 92 |
def test_show_should_display_watchers |
|
| 93 |
@request.session[:user_id] = 2 |
|
| 94 |
message = Message.find(1) |
|
| 95 |
message.add_watcher User.find(2) |
|
| 96 |
message.add_watcher Group.find(10) |
|
| 97 |
[['1', true], ['0', false]].each do |(gravatar_enabled, is_display_gravatar)| |
|
| 98 |
with_settings :gravatar_enabled => gravatar_enabled do |
|
| 99 |
get(:show, :params => {:board_id => 1, :id => 1})
|
|
| 100 |
end |
|
| 101 | ||
| 102 |
assert_select 'div#watchers ul' do |
|
| 103 |
assert_select 'li.user-2' do |
|
| 104 |
assert_select 'img.gravatar[title=?]', 'John Smith', is_display_gravatar |
|
| 105 |
assert_select 'a[href="/users/2"]' |
|
| 106 |
assert_select 'a[class*=delete]' |
|
| 107 |
end |
|
| 108 |
assert_select "li.user-10" do |
|
| 109 |
assert_select 'img.gravatar[title=?]', 'A Team', is_display_gravatar |
|
| 110 |
assert_select 'a[href="/users/10"]', false |
|
| 111 |
assert_select 'a[class*=delete]' |
|
| 112 |
end |
|
| 113 |
end |
|
| 114 |
end |
|
| 115 |
end |
|
| 116 | ||
| 91 | 117 |
def test_get_new |
| 92 | 118 |
@request.session[:user_id] = 2 |
| 93 | 119 |
get(:new, :params => {:board_id => 1})
|
| test/functional/watchers_controller_test.rb | ||
|---|---|---|
| 21 | 21 | |
| 22 | 22 |
class WatchersControllerTest < Redmine::ControllerTest |
| 23 | 23 |
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, |
| 24 |
:issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers |
|
| 24 |
:issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers, |
|
| 25 |
:boards, :messages |
|
| 25 | 26 | |
| 26 | 27 |
def setup |
| 27 | 28 |
User.current = nil |
| ... | ... | |
| 155 | 156 |
assert_match /ajax-modal/, response.body |
| 156 | 157 |
end |
| 157 | 158 | |
| 159 |
def test_new_for_message |
|
| 160 |
@request.session[:user_id] = 2 |
|
| 161 |
get :new, :params => {:object_type => 'message', :object_id => '1'}, :xhr => true
|
|
| 162 |
assert_response :success |
|
| 163 |
assert_match /ajax-modal/, response.body |
|
| 164 |
end |
|
| 165 | ||
| 158 | 166 |
def test_new_with_multiple_objects |
| 159 | 167 |
@request.session[:user_id] = 2 |
| 160 | 168 |
get :new, :params => {:object_type => 'issue', :object_id => ['1', '2']}, :xhr => true
|
| ... | ... | |
| 216 | 224 |
assert Issue.find(2).watched_by?(User.find(4)) |
| 217 | 225 |
end |
| 218 | 226 | |
| 227 |
def test_create_for_message |
|
| 228 |
@request.session[:user_id] = 2 |
|
| 229 |
assert_difference('Watcher.count') do
|
|
| 230 |
post :create, :params => {
|
|
| 231 |
:object_type => 'message', :object_id => '1', |
|
| 232 |
:watcher => {:user_id => '4'}
|
|
| 233 |
}, :xhr => true |
|
| 234 |
assert_response :success |
|
| 235 |
assert_match /watchers/, response.body |
|
| 236 |
assert_match /ajax-modal/, response.body |
|
| 237 |
end |
|
| 238 |
assert Message.find(1).watched_by?(User.find(4)) |
|
| 239 |
end |
|
| 240 | ||
| 219 | 241 |
def test_create_with_mutiple_users |
| 220 | 242 |
@request.session[:user_id] = 2 |
| 221 | 243 |
assert_difference('Watcher.count', 3) do
|
| ... | ... | |
| 233 | 255 |
assert issue.watched_by?(Group.find(10)) |
| 234 | 256 |
end |
| 235 | 257 | |
| 258 |
def test_create_for_message_with_mutiple_users |
|
| 259 |
@request.session[:user_id] = 2 |
|
| 260 |
assert_difference('Watcher.count', 3) do
|
|
| 261 |
post :create, :params => {
|
|
| 262 |
:object_type => 'message', :object_id => '1', |
|
| 263 |
:watcher => {:user_ids => ['4', '7', '10']}
|
|
| 264 |
}, :xhr => true |
|
| 265 |
assert_response :success |
|
| 266 |
assert_match /watchers/, response.body |
|
| 267 |
assert_match /ajax-modal/, response.body |
|
| 268 |
end |
|
| 269 |
message = Message.find(1) |
|
| 270 |
assert message.watched_by?(User.find(4)) |
|
| 271 |
assert message.watched_by?(User.find(7)) |
|
| 272 |
assert message.watched_by?(Group.find(10)) |
|
| 273 |
end |
|
| 274 | ||
| 236 | 275 |
def test_create_with_mutiple_objects |
| 237 | 276 |
@request.session[:user_id] = 2 |
| 238 | 277 |
assert_difference('Watcher.count', 6) do
|
| ... | ... | |
| 395 | 434 |
assert !Issue.find(2).watched_by?(User.find(3)) |
| 396 | 435 |
end |
| 397 | 436 | |
| 437 |
def test_destroy_for_meessage |
|
| 438 |
@request.session[:user_id] = 2 |
|
| 439 |
message = Message.find(1) |
|
| 440 |
user = User.find(1) |
|
| 441 |
assert message.watched_by?(user) |
|
| 442 |
assert_difference('Watcher.count', -1) do
|
|
| 443 |
delete :destroy, :params => {
|
|
| 444 |
:object_type => 'message', :object_id => '1', :user_id => '1' |
|
| 445 |
}, :xhr => true |
|
| 446 |
assert_response :success |
|
| 447 |
assert_match /watchers/, response.body |
|
| 448 |
end |
|
| 449 |
message.reload |
|
| 450 |
assert !message.watched_by?(user) |
|
| 451 |
end |
|
| 452 | ||
| 398 | 453 |
def test_destroy_locked_user |
| 399 | 454 |
user = User.find(3) |
| 400 | 455 |
user.lock! |