]> source.dussan.org Git - redmine.git/commitdiff
Adds the ability to move threads between project forums (#2452). 'Edit message' permi...
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 5 Apr 2009 10:08:11 +0000 (10:08 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 5 Apr 2009 10:08:11 +0000 (10:08 +0000)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2649 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/boards_controller.rb
app/controllers/messages_controller.rb
app/models/board.rb
app/models/message.rb
app/views/messages/_form.rhtml
test/fixtures/boards.yml
test/unit/message_test.rb

index 838e63a7c4bf9bfe5ea8e6f66d2e11880c605139..8d53f81e4bc40e149c68be6e6d36372a1b374302 100644 (file)
@@ -46,6 +46,7 @@ class BoardsController < ApplicationController
                                   :include => [:author, {:last_reply => :author}],
                                   :limit  =>  @topic_pages.items_per_page,
                                   :offset =>  @topic_pages.current.offset
+    @message = Message.new
     render :action => 'show', :layout => !request.xhr?
   end
   
index af39efb21890b9b9fcdad92ac62bf6373740eb3a..9a7c34c37ea0d799038260d23ad0ce5820334b95 100644 (file)
@@ -73,7 +73,8 @@ class MessagesController < ApplicationController
     if request.post? && @message.update_attributes(params[:message])
       attach_files(@message, params[:attachments])
       flash[:notice] = l(:notice_successful_update)
-      redirect_to :action => 'show', :id => @topic
+      @message.reload
+      redirect_to :action => 'show', :board_id => @message.board, :id => @message.root
     end
   end
   
index 26e2004d3bb4ea54e1a35de07f721e2ca0c7b3da..3bc18efec64ae926718f7ee885673a1840abec66 100644 (file)
@@ -26,4 +26,17 @@ class Board < ActiveRecord::Base
   validates_presence_of :name, :description
   validates_length_of :name, :maximum => 30
   validates_length_of :description, :maximum => 255
+  
+  def reset_counters!
+    self.class.reset_counters!(id)
+  end
+  
+  # Updates topics_count, messages_count and last_message_id attributes for +board_id+
+  def self.reset_counters!(board_id)
+    board_id = board_id.to_i
+    update_all("topics_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id} AND parent_id IS NULL)," +
+               " messages_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id})," +
+               " last_message_id = (SELECT MAX(id) FROM #{Message.table_name} WHERE board_id=#{board_id})",
+               ["id = ?", board_id])
+  end
 end
index 716c53b0b804420073a307088215f7f142fa3f5e..92bcb1275c6bb4101c42e7b0b769a01b4bbeb06e 100644 (file)
@@ -37,7 +37,7 @@ class Message < ActiveRecord::Base
   acts_as_watchable
     
   attr_protected :locked, :sticky
-  validates_presence_of :subject, :content
+  validates_presence_of :board, :subject, :content
   validates_length_of :subject, :maximum => 255
   
   after_create :add_author_as_watcher
@@ -48,21 +48,22 @@ class Message < ActiveRecord::Base
   end
   
   def after_create
-    board.update_attribute(:last_message_id, self.id)
-    board.increment! :messages_count
     if parent
       parent.reload.update_attribute(:last_reply_id, self.id)
-    else
-      board.increment! :topics_count
+    end
+    board.reset_counters!
+  end
+  
+  def after_update
+    if board_id_changed?
+      Message.update_all("board_id = #{board_id}", ["id = ? OR parent_id = ?", root.id, root.id])
+      Board.reset_counters!(board_id_was)
+      Board.reset_counters!(board_id)
     end
   end
   
   def after_destroy
-    # The following line is required so that the previous counter
-    # updates (due to children removal) are not overwritten
-    board.reload
-    board.decrement! :messages_count
-    board.decrement! :topics_count unless parent
+    board.reset_counters!
   end
   
   def sticky?
index 540811ec327eba7b7351a62adcc3e6f7db8fa04f..ab483bd5d5ebf65dc20b5cb1752d55b87c10d074 100644 (file)
 <% end %>
 </p>
 
+<% if !replying && !@message.new_record? && User.current.allowed_to?(:edit_messages, @project) %>
+       <p><label><%= l(:label_board) %></label><br />
+  <%= f.select :board_id, @project.boards.collect {|b| [b.name, b.id]} %></p>
+<% end %>
+
 <p><%= f.text_area :content, :cols => 80, :rows => 15, :class => 'wiki-edit', :id => 'message_content' %></p>
 <%= wikitoolbar_for 'message_content' %>
 <!--[eoform:message]-->
index b6b42aaa3e43b97940eb9f3e9d7ab4ec37cabde7..a4795c21e5a70613ac6242d5a5ce8bdad58d6c9a 100644 (file)
@@ -6,8 +6,8 @@ boards_001:
   id: 1\r
   description: Help board\r
   position: 1\r
-  last_message_id: 5\r
-  messages_count: 5\r
+  last_message_id: 6\r
+  messages_count: 6\r
 boards_002: \r
   name: Discussion\r
   project_id: 1\r
index b907cfef327bb33fbac353e1fc840a9b8f18d419..bc9bd5fd361907b0e12c74aa094e8cacfbcb08c1 100644 (file)
@@ -1,3 +1,20 @@
+# Redmine - project management software
+# Copyright (C) 2006-2009  Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
 require File.dirname(__FILE__) + '/../test_helper'
 
 class MessageTest < Test::Unit::TestCase
@@ -47,6 +64,23 @@ class MessageTest < Test::Unit::TestCase
     assert @message.watched_by?(reply_author)
   end
   
+  def test_moving_message_should_update_counters
+    @message = Message.find(1)
+    assert_no_difference 'Message.count' do
+      # Previous board
+      assert_difference 'Board.find(1).topics_count', -1 do
+        assert_difference 'Board.find(1).messages_count', -(1 + @message.replies_count) do
+          # New board
+          assert_difference 'Board.find(2).topics_count' do
+            assert_difference 'Board.find(2).messages_count', (1 + @message.replies_count) do
+              @message.update_attributes(:board_id => 2)
+            end
+          end
+        end
+      end
+    end
+  end
+  
   def test_destroy_topic
     message = Message.find(1)
     board = message.board