diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb
new file mode 100644
index 00000000..b3be6b7a
--- /dev/null
+++ b/app/controllers/boards_controller.rb
@@ -0,0 +1,87 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 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.
+
+class BoardsController < ApplicationController
+ layout 'base'
+ before_filter :find_project
+ before_filter :authorize, :except => [:index, :show]
+ before_filter :check_project_privacy, :only => [:index, :show]
+
+ helper :messages
+ include MessagesHelper
+ helper :sort
+ include SortHelper
+
+ def index
+ @boards = @project.boards
+ # show the board if there is only one
+ if @boards.size == 1
+ @board = @boards.first
+ show
+ render :action => 'show'
+ end
+ end
+
+ def show
+ sort_init "#{Message.table_name}.updated_on", "desc"
+ sort_update
+
+ @topic_count = @board.topics.count
+ @topic_pages = Paginator.new self, @topic_count, 25, params['page']
+ @topics = @board.topics.find :all, :order => sort_clause,
+ :include => [:author, {:last_reply => :author}],
+ :limit => @topic_pages.items_per_page,
+ :offset => @topic_pages.current.offset
+ render :action => 'show', :layout => false if request.xhr?
+ end
+
+ verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :index }
+
+ def new
+ @board = Board.new(params[:board])
+ @board.project = @project
+ if request.post? && @board.save
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards'
+ end
+ end
+
+ def edit
+ if request.post? && @board.update_attributes(params[:board])
+ case params[:position]
+ when 'highest'; @board.move_to_top
+ when 'higher'; @board.move_higher
+ when 'lower'; @board.move_lower
+ when 'lowest'; @board.move_to_bottom
+ end if params[:position]
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards'
+ end
+ end
+
+ def destroy
+ @board.destroy
+ redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards'
+ end
+
+private
+ def find_project
+ @project = Project.find(params[:project_id])
+ @board = @project.boards.find(params[:id]) if params[:id]
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
+end
diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb
new file mode 100644
index 00000000..16a04097
--- /dev/null
+++ b/app/controllers/messages_controller.rb
@@ -0,0 +1,66 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 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.
+
+class MessagesController < ApplicationController
+ layout 'base'
+ before_filter :find_project, :check_project_privacy
+ before_filter :require_login, :only => [:new, :reply]
+
+ verify :method => :post, :only => [ :reply, :destroy ], :redirect_to => { :action => :show }
+
+ def show
+ @reply = Message.new(:subject => "RE: #{@message.subject}")
+ render :action => "show", :layout => false if request.xhr?
+ end
+
+ def new
+ @message = Message.new(params[:message])
+ @message.author = logged_in_user
+ @message.board = @board
+ if request.post? && @message.save
+ params[:attachments].each { |file|
+ next unless file.size > 0
+ Attachment.create(:container => @message, :file => file, :author => logged_in_user)
+ } if params[:attachments] and params[:attachments].is_a? Array
+ redirect_to :action => 'show', :id => @message
+ end
+ end
+
+ def reply
+ @reply = Message.new(params[:reply])
+ @reply.author = logged_in_user
+ @reply.board = @board
+ @message.children << @reply
+ redirect_to :action => 'show', :id => @message
+ end
+
+ def download
+ @attachment = @message.attachments.find(params[:attachment_id])
+ send_file @attachment.diskfile, :filename => @attachment.filename
+ rescue
+ render_404
+ end
+
+private
+ def find_project
+ @board = Board.find(params[:board_id], :include => :project)
+ @project = @board.project
+ @message = @board.topics.find(params[:id]) if params[:id]
+ rescue ActiveRecord::RecordNotFound
+ render_404
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index f5d26296..cd1b2ea0 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -215,6 +215,11 @@ module ApplicationHelper
image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
end
+
+ def wikitoolbar_for(field_id)
+ return '' unless Setting.text_formatting == 'textile'
+ javascript_include_tag('jstoolbar') + javascript_tag("var toolbar = new jsToolBar($('#{field_id}')); toolbar.draw();")
+ end
end
class TabularFormBuilder < ActionView::Helpers::FormBuilder
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
new file mode 100644
index 00000000..3719e0fe
--- /dev/null
+++ b/app/helpers/boards_helper.rb
@@ -0,0 +1,19 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 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.
+
+module BoardsHelper
+end
diff --git a/app/helpers/messages_helper.rb b/app/helpers/messages_helper.rb
new file mode 100644
index 00000000..bf23275c
--- /dev/null
+++ b/app/helpers/messages_helper.rb
@@ -0,0 +1,28 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 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.
+
+module MessagesHelper
+
+ def link_to_message(message)
+ return '' unless message
+ link_to h(truncate(message.subject, 60)), :controller => 'messages',
+ :action => 'show',
+ :board_id => message.board_id,
+ :id => message.root,
+ :anchor => (message.parent_id ? "message-#{message.id}" : nil)
+ end
+end
diff --git a/app/models/board.rb b/app/models/board.rb
new file mode 100644
index 00000000..a6ea22f6
--- /dev/null
+++ b/app/models/board.rb
@@ -0,0 +1,28 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 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.
+
+class Board < ActiveRecord::Base
+ belongs_to :project
+ has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC"
+ has_many :messages, :dependent => :delete_all, :order => "#{Message.table_name}.created_on DESC"
+ belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id
+ acts_as_list :scope => :project_id
+
+ validates_presence_of :name, :description
+ validates_length_of :name, :maximum => 30
+ validates_length_of :description, :maximum => 255
+end
diff --git a/app/models/message.rb b/app/models/message.rb
new file mode 100644
index 00000000..1f8dde54
--- /dev/null
+++ b/app/models/message.rb
@@ -0,0 +1,37 @@
+# redMine - project management software
+# Copyright (C) 2006-2007 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.
+
+class Message < ActiveRecord::Base
+ belongs_to :board
+ belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
+ acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
+ has_many :attachments, :as => :container, :dependent => :destroy
+ belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
+
+ validates_presence_of :subject, :content
+ validates_length_of :subject, :maximum => 255
+
+ 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
+ end
+end
diff --git a/app/models/permission.rb b/app/models/permission.rb
index 609d5d56..f78118d8 100644
--- a/app/models/permission.rb
+++ b/app/models/permission.rb
@@ -31,7 +31,8 @@ class Permission < ActiveRecord::Base
1200 => :label_document_plural,
1300 => :label_attachment_plural,
1400 => :label_repository,
- 1500 => :label_time_tracking
+ 1500 => :label_time_tracking,
+ 2000 => :label_board_plural
}.freeze
@@cached_perms_for_public = nil
diff --git a/app/models/project.rb b/app/models/project.rb
index 018efe37..6dd6b264 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -26,6 +26,7 @@ class Project < ActiveRecord::Base
has_many :documents, :dependent => :destroy
has_many :news, :dependent => :delete_all, :include => :author
has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
+ has_many :boards, :order => "position ASC"
has_one :repository, :dependent => :destroy
has_one :wiki, :dependent => :destroy
has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :association_foreign_key => 'custom_field_id'
diff --git a/app/views/boards/_form.rhtml b/app/views/boards/_form.rhtml
new file mode 100644
index 00000000..7ede589a
--- /dev/null
+++ b/app/views/boards/_form.rhtml
@@ -0,0 +1,8 @@
+<%= error_messages_for 'board' %>
+
+
+