@@ -0,0 +1,14 | |||
|
1 | class SetTopicAuthorsAsWatchers < ActiveRecord::Migration | |
|
2 | def self.up | |
|
3 | # Sets active users who created/replied a topic as watchers of the topic | |
|
4 | # so that the new watch functionality at topic level doesn't affect notifications behaviour | |
|
5 | Message.connection.execute("INSERT INTO watchers (watchable_type, watchable_id, user_id)" + | |
|
6 | " SELECT DISTINCT 'Message', COALESCE(messages.parent_id, messages.id), messages.author_id FROM messages, users" + | |
|
7 | " WHERE messages.author_id = users.id AND users.status = 1") | |
|
8 | end | |
|
9 | ||
|
10 | def self.down | |
|
11 | # Removes all message watchers | |
|
12 | Watcher.delete_all("watchable_type = 'Message'") | |
|
13 | end | |
|
14 | end |
@@ -24,7 +24,7 class MessagesController < ApplicationController | |||
|
24 | 24 | verify :method => :post, :only => [ :reply, :destroy ], :redirect_to => { :action => :show } |
|
25 | 25 | verify :xhr => true, :only => :quote |
|
26 | 26 | |
|
27 | ||
|
27 | helper :watchers | |
|
28 | 28 | helper :attachments |
|
29 | 29 | include AttachmentsHelper |
|
30 | 30 |
@@ -33,11 +33,14 class Message < ActiveRecord::Base | |||
|
33 | 33 | {:id => o.parent_id, :anchor => "message-#{o.id}"})} |
|
34 | 34 | |
|
35 | 35 | acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]} |
|
36 | acts_as_watchable | |
|
36 | 37 | |
|
37 | 38 | attr_protected :locked, :sticky |
|
38 | 39 | validates_presence_of :subject, :content |
|
39 | 40 | validates_length_of :subject, :maximum => 255 |
|
40 | 41 | |
|
42 | after_create :add_author_as_watcher | |
|
43 | ||
|
41 | 44 | def validate_on_create |
|
42 | 45 | # Can not reply to a locked topic |
|
43 | 46 | errors.add_to_base 'Topic is locked' if root.locked? && self != root |
@@ -68,4 +71,10 class Message < ActiveRecord::Base | |||
|
68 | 71 | def project |
|
69 | 72 | board.project |
|
70 | 73 | end |
|
74 | ||
|
75 | private | |
|
76 | ||
|
77 | def add_author_as_watcher | |
|
78 | Watcher.create(:watchable => self.root, :user => author) | |
|
79 | end | |
|
71 | 80 | end |
@@ -17,8 +17,9 | |||
|
17 | 17 | |
|
18 | 18 | class MessageObserver < ActiveRecord::Observer |
|
19 | 19 | def after_create(message) |
|
20 | # send notification to the authors of the thread | |
|
21 | recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author && m.author.active?} | |
|
20 | recipients = [] | |
|
21 | # send notification to the topic watchers | |
|
22 | recipients += message.root.watcher_recipients | |
|
22 | 23 | # send notification to the board watchers |
|
23 | 24 | recipients += message.board.watcher_recipients |
|
24 | 25 | # send notification to project members who want to be notified |
@@ -2,6 +2,7 | |||
|
2 | 2 | link_to(h(@board.name), {:controller => 'boards', :action => 'show', :project_id => @project, :id => @board}) %> |
|
3 | 3 | |
|
4 | 4 | <div class="contextual"> |
|
5 | <%= watcher_tag(@topic, User.current) %> | |
|
5 | 6 | <%= link_to_remote_if_authorized l(:button_quote), { :url => {:action => 'quote', :id => @topic} }, :class => 'icon icon-comment' %> |
|
6 | 7 | <%= link_to_if_authorized l(:button_edit), {:action => 'edit', :id => @topic}, :class => 'icon icon-edit' %> |
|
7 | 8 | <%= link_to_if_authorized l(:button_delete), {:action => 'destroy', :id => @topic}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del' %> |
@@ -3,4 +3,8 watchers_001: | |||
|
3 | 3 | watchable_type: Issue |
|
4 | 4 | watchable_id: 2 |
|
5 | 5 | user_id: 3 |
|
6 | watchers_002: | |
|
7 | watchable_type: Message | |
|
8 | watchable_id: 1 | |
|
9 | user_id: 1 | |
|
6 | 10 | No newline at end of file |
@@ -1,7 +1,7 | |||
|
1 | 1 | require File.dirname(__FILE__) + '/../test_helper' |
|
2 | 2 | |
|
3 | 3 | class MessageTest < Test::Unit::TestCase |
|
4 | fixtures :projects, :boards, :messages | |
|
4 | fixtures :projects, :boards, :messages, :users, :watchers | |
|
5 | 5 | |
|
6 | 6 | def setup |
|
7 | 7 | @board = Board.find(1) |
@@ -20,6 +20,8 class MessageTest < Test::Unit::TestCase | |||
|
20 | 20 | # messages count incremented |
|
21 | 21 | assert_equal messages_count+1, @board[:messages_count] |
|
22 | 22 | assert_equal message, @board.last_message |
|
23 | # author should be watching the message | |
|
24 | assert message.watched_by?(@user) | |
|
23 | 25 | end |
|
24 | 26 | |
|
25 | 27 | def test_reply |
@@ -28,7 +30,8 class MessageTest < Test::Unit::TestCase | |||
|
28 | 30 | @message = Message.find(1) |
|
29 | 31 | replies_count = @message.replies_count |
|
30 | 32 | |
|
31 | reply = Message.new(:board => @board, :subject => 'Test reply', :content => 'Test reply content', :parent => @message, :author => @user) | |
|
33 | reply_author = User.find(2) | |
|
34 | reply = Message.new(:board => @board, :subject => 'Test reply', :content => 'Test reply content', :parent => @message, :author => reply_author) | |
|
32 | 35 | assert reply.save |
|
33 | 36 | @board.reload |
|
34 | 37 | # same topics count |
@@ -40,13 +43,18 class MessageTest < Test::Unit::TestCase | |||
|
40 | 43 | # replies count incremented |
|
41 | 44 | assert_equal replies_count+1, @message[:replies_count] |
|
42 | 45 | assert_equal reply, @message.last_reply |
|
46 | # author should be watching the message | |
|
47 | assert @message.watched_by?(reply_author) | |
|
43 | 48 | end |
|
44 | 49 | |
|
45 | 50 | def test_destroy_topic |
|
46 | 51 | message = Message.find(1) |
|
47 | 52 | board = message.board |
|
48 | 53 | topics_count, messages_count = board.topics_count, board.messages_count |
|
54 | ||
|
55 | assert_difference('Watcher.count', -1) do | |
|
49 | 56 | assert message.destroy |
|
57 | end | |
|
50 | 58 | board.reload |
|
51 | 59 | |
|
52 | 60 | # Replies deleted |
@@ -54,6 +62,7 class MessageTest < Test::Unit::TestCase | |||
|
54 | 62 | # Checks counters |
|
55 | 63 | assert_equal topics_count - 1, board.topics_count |
|
56 | 64 | assert_equal messages_count - 3, board.messages_count |
|
65 | # Watchers removed | |
|
57 | 66 | end |
|
58 | 67 | |
|
59 | 68 | def test_destroy_reply |
General Comments 0
You need to be logged in to leave comments.
Login now