##// END OF EJS Templates
Prevent SQL error with old sessions after r2171....
Jean-Philippe Lang -
r2181:fb1f72a09c64
parent child
Show More
@@ -1,87 +1,87
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class BoardsController < ApplicationController
18 class BoardsController < ApplicationController
19 before_filter :find_project, :authorize
19 before_filter :find_project, :authorize
20
20
21 helper :messages
21 helper :messages
22 include MessagesHelper
22 include MessagesHelper
23 helper :sort
23 helper :sort
24 include SortHelper
24 include SortHelper
25 helper :watchers
25 helper :watchers
26 include WatchersHelper
26 include WatchersHelper
27
27
28 def index
28 def index
29 @boards = @project.boards
29 @boards = @project.boards
30 # show the board if there is only one
30 # show the board if there is only one
31 if @boards.size == 1
31 if @boards.size == 1
32 @board = @boards.first
32 @board = @boards.first
33 show
33 show
34 end
34 end
35 end
35 end
36
36
37 def show
37 def show
38 sort_init 'updated_on', 'desc'
38 sort_init 'updated_on', 'desc'
39 sort_update 'created_on' => "#{Message.table_name}.created_on",
39 sort_update 'created_on' => "#{Message.table_name}.created_on",
40 'replies' => "#{Message.table_name}.replies_count",
40 'replies' => "#{Message.table_name}.replies_count",
41 'updated_on' => "#{Message.table_name}.updated_on"
41 'updated_on' => "#{Message.table_name}.updated_on"
42
42
43 @topic_count = @board.topics.count
43 @topic_count = @board.topics.count
44 @topic_pages = Paginator.new self, @topic_count, per_page_option, params['page']
44 @topic_pages = Paginator.new self, @topic_count, per_page_option, params['page']
45 @topics = @board.topics.find :all, :order => "#{Message.table_name}.sticky DESC, #{sort_clause}",
45 @topics = @board.topics.find :all, :order => ["#{Message.table_name}.sticky DESC", sort_clause].compact.join(', '),
46 :include => [:author, {:last_reply => :author}],
46 :include => [:author, {:last_reply => :author}],
47 :limit => @topic_pages.items_per_page,
47 :limit => @topic_pages.items_per_page,
48 :offset => @topic_pages.current.offset
48 :offset => @topic_pages.current.offset
49 render :action => 'show', :layout => !request.xhr?
49 render :action => 'show', :layout => !request.xhr?
50 end
50 end
51
51
52 verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :index }
52 verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :index }
53
53
54 def new
54 def new
55 @board = Board.new(params[:board])
55 @board = Board.new(params[:board])
56 @board.project = @project
56 @board.project = @project
57 if request.post? && @board.save
57 if request.post? && @board.save
58 flash[:notice] = l(:notice_successful_create)
58 flash[:notice] = l(:notice_successful_create)
59 redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards'
59 redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards'
60 end
60 end
61 end
61 end
62
62
63 def edit
63 def edit
64 if request.post? && @board.update_attributes(params[:board])
64 if request.post? && @board.update_attributes(params[:board])
65 case params[:position]
65 case params[:position]
66 when 'highest'; @board.move_to_top
66 when 'highest'; @board.move_to_top
67 when 'higher'; @board.move_higher
67 when 'higher'; @board.move_higher
68 when 'lower'; @board.move_lower
68 when 'lower'; @board.move_lower
69 when 'lowest'; @board.move_to_bottom
69 when 'lowest'; @board.move_to_bottom
70 end if params[:position]
70 end if params[:position]
71 redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards'
71 redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards'
72 end
72 end
73 end
73 end
74
74
75 def destroy
75 def destroy
76 @board.destroy
76 @board.destroy
77 redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards'
77 redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards'
78 end
78 end
79
79
80 private
80 private
81 def find_project
81 def find_project
82 @project = Project.find(params[:project_id])
82 @project = Project.find(params[:project_id])
83 @board = @project.boards.find(params[:id]) if params[:id]
83 @board = @project.boards.find(params[:id]) if params[:id]
84 rescue ActiveRecord::RecordNotFound
84 rescue ActiveRecord::RecordNotFound
85 render_404
85 render_404
86 end
86 end
87 end
87 end
@@ -1,168 +1,168
1 # Helpers to sort tables using clickable column headers.
1 # Helpers to sort tables using clickable column headers.
2 #
2 #
3 # Author: Stuart Rackham <srackham@methods.co.nz>, March 2005.
3 # Author: Stuart Rackham <srackham@methods.co.nz>, March 2005.
4 # License: This source code is released under the MIT license.
4 # License: This source code is released under the MIT license.
5 #
5 #
6 # - Consecutive clicks toggle the column's sort order.
6 # - Consecutive clicks toggle the column's sort order.
7 # - Sort state is maintained by a session hash entry.
7 # - Sort state is maintained by a session hash entry.
8 # - Icon image identifies sort column and state.
8 # - Icon image identifies sort column and state.
9 # - Typically used in conjunction with the Pagination module.
9 # - Typically used in conjunction with the Pagination module.
10 #
10 #
11 # Example code snippets:
11 # Example code snippets:
12 #
12 #
13 # Controller:
13 # Controller:
14 #
14 #
15 # helper :sort
15 # helper :sort
16 # include SortHelper
16 # include SortHelper
17 #
17 #
18 # def list
18 # def list
19 # sort_init 'last_name'
19 # sort_init 'last_name'
20 # sort_update
20 # sort_update
21 # @items = Contact.find_all nil, sort_clause
21 # @items = Contact.find_all nil, sort_clause
22 # end
22 # end
23 #
23 #
24 # Controller (using Pagination module):
24 # Controller (using Pagination module):
25 #
25 #
26 # helper :sort
26 # helper :sort
27 # include SortHelper
27 # include SortHelper
28 #
28 #
29 # def list
29 # def list
30 # sort_init 'last_name'
30 # sort_init 'last_name'
31 # sort_update
31 # sort_update
32 # @contact_pages, @items = paginate :contacts,
32 # @contact_pages, @items = paginate :contacts,
33 # :order_by => sort_clause,
33 # :order_by => sort_clause,
34 # :per_page => 10
34 # :per_page => 10
35 # end
35 # end
36 #
36 #
37 # View (table header in list.rhtml):
37 # View (table header in list.rhtml):
38 #
38 #
39 # <thead>
39 # <thead>
40 # <tr>
40 # <tr>
41 # <%= sort_header_tag('id', :title => 'Sort by contact ID') %>
41 # <%= sort_header_tag('id', :title => 'Sort by contact ID') %>
42 # <%= sort_header_tag('last_name', :caption => 'Name') %>
42 # <%= sort_header_tag('last_name', :caption => 'Name') %>
43 # <%= sort_header_tag('phone') %>
43 # <%= sort_header_tag('phone') %>
44 # <%= sort_header_tag('address', :width => 200) %>
44 # <%= sort_header_tag('address', :width => 200) %>
45 # </tr>
45 # </tr>
46 # </thead>
46 # </thead>
47 #
47 #
48 # - The ascending and descending sort icon images are sort_asc.png and
48 # - The ascending and descending sort icon images are sort_asc.png and
49 # sort_desc.png and reside in the application's images directory.
49 # sort_desc.png and reside in the application's images directory.
50 # - Introduces instance variables: @sort_name, @sort_default.
50 # - Introduces instance variables: @sort_name, @sort_default.
51 # - Introduces params :sort_key and :sort_order.
51 # - Introduces params :sort_key and :sort_order.
52 #
52 #
53 module SortHelper
53 module SortHelper
54
54
55 # Initializes the default sort column (default_key) and sort order
55 # Initializes the default sort column (default_key) and sort order
56 # (default_order).
56 # (default_order).
57 #
57 #
58 # - default_key is a column attribute name.
58 # - default_key is a column attribute name.
59 # - default_order is 'asc' or 'desc'.
59 # - default_order is 'asc' or 'desc'.
60 # - name is the name of the session hash entry that stores the sort state,
60 # - name is the name of the session hash entry that stores the sort state,
61 # defaults to '<controller_name>_sort'.
61 # defaults to '<controller_name>_sort'.
62 #
62 #
63 def sort_init(default_key, default_order='asc', name=nil)
63 def sort_init(default_key, default_order='asc', name=nil)
64 @sort_name = name || params[:controller] + params[:action] + '_sort'
64 @sort_name = name || params[:controller] + params[:action] + '_sort'
65 @sort_default = {:key => default_key, :order => default_order}
65 @sort_default = {:key => default_key, :order => default_order}
66 end
66 end
67
67
68 # Updates the sort state. Call this in the controller prior to calling
68 # Updates the sort state. Call this in the controller prior to calling
69 # sort_clause.
69 # sort_clause.
70 # sort_keys can be either an array or a hash of allowed keys
70 # sort_keys can be either an array or a hash of allowed keys
71 def sort_update(sort_keys)
71 def sort_update(sort_keys)
72 sort_key = params[:sort_key]
72 sort_key = params[:sort_key]
73 sort_key = nil unless (sort_keys.is_a?(Array) ? sort_keys.include?(sort_key) : sort_keys[sort_key])
73 sort_key = nil unless (sort_keys.is_a?(Array) ? sort_keys.include?(sort_key) : sort_keys[sort_key])
74
74
75 sort_order = (params[:sort_order] == 'desc' ? 'DESC' : 'ASC')
75 sort_order = (params[:sort_order] == 'desc' ? 'DESC' : 'ASC')
76
76
77 if sort_key
77 if sort_key
78 sort = {:key => sort_key, :order => sort_order}
78 sort = {:key => sort_key, :order => sort_order}
79 elsif session[@sort_name]
79 elsif session[@sort_name]
80 sort = session[@sort_name] # Previous sort.
80 sort = session[@sort_name] # Previous sort.
81 else
81 else
82 sort = @sort_default
82 sort = @sort_default
83 end
83 end
84 session[@sort_name] = sort
84 session[@sort_name] = sort
85
85
86 sort_column = (sort_keys.is_a?(Hash) ? sort_keys[sort[:key]] : sort[:key])
86 sort_column = (sort_keys.is_a?(Hash) ? sort_keys[sort[:key]] : sort[:key])
87 @sort_clause = (sort_column.blank? ? '' : "#{sort_column} #{sort[:order]}")
87 @sort_clause = (sort_column.blank? ? nil : "#{sort_column} #{sort[:order]}")
88 end
88 end
89
89
90 # Returns an SQL sort clause corresponding to the current sort state.
90 # Returns an SQL sort clause corresponding to the current sort state.
91 # Use this to sort the controller's table items collection.
91 # Use this to sort the controller's table items collection.
92 #
92 #
93 def sort_clause()
93 def sort_clause()
94 @sort_clause || '' #session[@sort_name][:key] + ' ' + (session[@sort_name][:order] || 'ASC')
94 @sort_clause
95 end
95 end
96
96
97 # Returns a link which sorts by the named column.
97 # Returns a link which sorts by the named column.
98 #
98 #
99 # - column is the name of an attribute in the sorted record collection.
99 # - column is the name of an attribute in the sorted record collection.
100 # - The optional caption explicitly specifies the displayed link text.
100 # - The optional caption explicitly specifies the displayed link text.
101 # - A sort icon image is positioned to the right of the sort link.
101 # - A sort icon image is positioned to the right of the sort link.
102 #
102 #
103 def sort_link(column, caption, default_order)
103 def sort_link(column, caption, default_order)
104 key, order = session[@sort_name][:key], session[@sort_name][:order]
104 key, order = session[@sort_name][:key], session[@sort_name][:order]
105 if key == column
105 if key == column
106 if order.downcase == 'asc'
106 if order.downcase == 'asc'
107 icon = 'sort_asc.png'
107 icon = 'sort_asc.png'
108 order = 'desc'
108 order = 'desc'
109 else
109 else
110 icon = 'sort_desc.png'
110 icon = 'sort_desc.png'
111 order = 'asc'
111 order = 'asc'
112 end
112 end
113 else
113 else
114 icon = nil
114 icon = nil
115 order = default_order
115 order = default_order
116 end
116 end
117 caption = titleize(Inflector::humanize(column)) unless caption
117 caption = titleize(Inflector::humanize(column)) unless caption
118
118
119 sort_options = { :sort_key => column, :sort_order => order }
119 sort_options = { :sort_key => column, :sort_order => order }
120 # don't reuse params if filters are present
120 # don't reuse params if filters are present
121 url_options = params.has_key?(:set_filter) ? sort_options : params.merge(sort_options)
121 url_options = params.has_key?(:set_filter) ? sort_options : params.merge(sort_options)
122
122
123 link_to_remote(caption,
123 link_to_remote(caption,
124 {:update => "content", :url => url_options},
124 {:update => "content", :url => url_options},
125 {:href => url_for(url_options)}) +
125 {:href => url_for(url_options)}) +
126 (icon ? nbsp(2) + image_tag(icon) : '')
126 (icon ? nbsp(2) + image_tag(icon) : '')
127 end
127 end
128
128
129 # Returns a table header <th> tag with a sort link for the named column
129 # Returns a table header <th> tag with a sort link for the named column
130 # attribute.
130 # attribute.
131 #
131 #
132 # Options:
132 # Options:
133 # :caption The displayed link name (defaults to titleized column name).
133 # :caption The displayed link name (defaults to titleized column name).
134 # :title The tag's 'title' attribute (defaults to 'Sort by :caption').
134 # :title The tag's 'title' attribute (defaults to 'Sort by :caption').
135 #
135 #
136 # Other options hash entries generate additional table header tag attributes.
136 # Other options hash entries generate additional table header tag attributes.
137 #
137 #
138 # Example:
138 # Example:
139 #
139 #
140 # <%= sort_header_tag('id', :title => 'Sort by contact ID', :width => 40) %>
140 # <%= sort_header_tag('id', :title => 'Sort by contact ID', :width => 40) %>
141 #
141 #
142 # Renders:
142 # Renders:
143 #
143 #
144 # <th title="Sort by contact ID" width="40">
144 # <th title="Sort by contact ID" width="40">
145 # <a href="/contact/list?sort_order=desc&amp;sort_key=id">Id</a>
145 # <a href="/contact/list?sort_order=desc&amp;sort_key=id">Id</a>
146 # &nbsp;&nbsp;<img alt="Sort_asc" src="/images/sort_asc.png" />
146 # &nbsp;&nbsp;<img alt="Sort_asc" src="/images/sort_asc.png" />
147 # </th>
147 # </th>
148 #
148 #
149 def sort_header_tag(column, options = {})
149 def sort_header_tag(column, options = {})
150 caption = options.delete(:caption) || titleize(Inflector::humanize(column))
150 caption = options.delete(:caption) || titleize(Inflector::humanize(column))
151 default_order = options.delete(:default_order) || 'asc'
151 default_order = options.delete(:default_order) || 'asc'
152 options[:title]= l(:label_sort_by, "\"#{caption}\"") unless options[:title]
152 options[:title]= l(:label_sort_by, "\"#{caption}\"") unless options[:title]
153 content_tag('th', sort_link(column, caption, default_order), options)
153 content_tag('th', sort_link(column, caption, default_order), options)
154 end
154 end
155
155
156 private
156 private
157
157
158 # Return n non-breaking spaces.
158 # Return n non-breaking spaces.
159 def nbsp(n)
159 def nbsp(n)
160 '&nbsp;' * n
160 '&nbsp;' * n
161 end
161 end
162
162
163 # Return capitalized title.
163 # Return capitalized title.
164 def titleize(title)
164 def titleize(title)
165 title.split.map {|w| w.capitalize }.join(' ')
165 title.split.map {|w| w.capitalize }.join(' ')
166 end
166 end
167
167
168 end
168 end
General Comments 0
You need to be logged in to leave comments. Login now