##// END OF EJS Templates
Refactor: change :id on WikiController to use :project_id...
Eric Davis -
r4151:d3381fb518d7
parent child
Show More
@@ -1,247 +1,247
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 require 'diff'
18 require 'diff'
19
19
20 class WikiController < ApplicationController
20 class WikiController < ApplicationController
21 default_search_scope :wiki_pages
21 default_search_scope :wiki_pages
22 before_filter :find_wiki, :authorize
22 before_filter :find_wiki, :authorize
23 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
23 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
24
24
25 verify :method => :post, :only => [:destroy, :protect], :redirect_to => { :action => :index }
25 verify :method => :post, :only => [:destroy, :protect], :redirect_to => { :action => :index }
26
26
27 helper :attachments
27 helper :attachments
28 include AttachmentsHelper
28 include AttachmentsHelper
29 helper :watchers
29 helper :watchers
30
30
31 # display a page (in editing mode if it doesn't exist)
31 # display a page (in editing mode if it doesn't exist)
32 def index
32 def index
33 page_title = params[:page]
33 page_title = params[:page]
34 @page = @wiki.find_or_new_page(page_title)
34 @page = @wiki.find_or_new_page(page_title)
35 if @page.new_record?
35 if @page.new_record?
36 if User.current.allowed_to?(:edit_wiki_pages, @project) && editable?
36 if User.current.allowed_to?(:edit_wiki_pages, @project) && editable?
37 edit
37 edit
38 render :action => 'edit'
38 render :action => 'edit'
39 else
39 else
40 render_404
40 render_404
41 end
41 end
42 return
42 return
43 end
43 end
44 if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
44 if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
45 # Redirects user to the current version if he's not allowed to view previous versions
45 # Redirects user to the current version if he's not allowed to view previous versions
46 redirect_to :version => nil
46 redirect_to :version => nil
47 return
47 return
48 end
48 end
49 @content = @page.content_for_version(params[:version])
49 @content = @page.content_for_version(params[:version])
50 if User.current.allowed_to?(:export_wiki_pages, @project)
50 if User.current.allowed_to?(:export_wiki_pages, @project)
51 if params[:format] == 'html'
51 if params[:format] == 'html'
52 export = render_to_string :action => 'export', :layout => false
52 export = render_to_string :action => 'export', :layout => false
53 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
53 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
54 return
54 return
55 elsif params[:format] == 'txt'
55 elsif params[:format] == 'txt'
56 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
56 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
57 return
57 return
58 end
58 end
59 end
59 end
60 @editable = editable?
60 @editable = editable?
61 render :action => 'show'
61 render :action => 'show'
62 end
62 end
63
63
64 # edit an existing page or a new one
64 # edit an existing page or a new one
65 def edit
65 def edit
66 @page = @wiki.find_or_new_page(params[:page])
66 @page = @wiki.find_or_new_page(params[:page])
67 return render_403 unless editable?
67 return render_403 unless editable?
68 @page.content = WikiContent.new(:page => @page) if @page.new_record?
68 @page.content = WikiContent.new(:page => @page) if @page.new_record?
69
69
70 @content = @page.content_for_version(params[:version])
70 @content = @page.content_for_version(params[:version])
71 @content.text = initial_page_content(@page) if @content.text.blank?
71 @content.text = initial_page_content(@page) if @content.text.blank?
72 # don't keep previous comment
72 # don't keep previous comment
73 @content.comments = nil
73 @content.comments = nil
74 if request.get?
74 if request.get?
75 # To prevent StaleObjectError exception when reverting to a previous version
75 # To prevent StaleObjectError exception when reverting to a previous version
76 @content.version = @page.content.version
76 @content.version = @page.content.version
77 else
77 else
78 if !@page.new_record? && @content.text == params[:content][:text]
78 if !@page.new_record? && @content.text == params[:content][:text]
79 attachments = Attachment.attach_files(@page, params[:attachments])
79 attachments = Attachment.attach_files(@page, params[:attachments])
80 render_attachment_warning_if_needed(@page)
80 render_attachment_warning_if_needed(@page)
81 # don't save if text wasn't changed
81 # don't save if text wasn't changed
82 redirect_to :action => 'index', :id => @project, :page => @page.title
82 redirect_to :action => 'index', :project_id => @project, :page => @page.title
83 return
83 return
84 end
84 end
85 #@content.text = params[:content][:text]
85 #@content.text = params[:content][:text]
86 #@content.comments = params[:content][:comments]
86 #@content.comments = params[:content][:comments]
87 @content.attributes = params[:content]
87 @content.attributes = params[:content]
88 @content.author = User.current
88 @content.author = User.current
89 # if page is new @page.save will also save content, but not if page isn't a new record
89 # if page is new @page.save will also save content, but not if page isn't a new record
90 if (@page.new_record? ? @page.save : @content.save)
90 if (@page.new_record? ? @page.save : @content.save)
91 attachments = Attachment.attach_files(@page, params[:attachments])
91 attachments = Attachment.attach_files(@page, params[:attachments])
92 render_attachment_warning_if_needed(@page)
92 render_attachment_warning_if_needed(@page)
93 call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
93 call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
94 redirect_to :action => 'index', :id => @project, :page => @page.title
94 redirect_to :action => 'index', :project_id => @project, :page => @page.title
95 end
95 end
96 end
96 end
97 rescue ActiveRecord::StaleObjectError
97 rescue ActiveRecord::StaleObjectError
98 # Optimistic locking exception
98 # Optimistic locking exception
99 flash[:error] = l(:notice_locking_conflict)
99 flash[:error] = l(:notice_locking_conflict)
100 end
100 end
101
101
102 # rename a page
102 # rename a page
103 def rename
103 def rename
104 return render_403 unless editable?
104 return render_403 unless editable?
105 @page.redirect_existing_links = true
105 @page.redirect_existing_links = true
106 # used to display the *original* title if some AR validation errors occur
106 # used to display the *original* title if some AR validation errors occur
107 @original_title = @page.pretty_title
107 @original_title = @page.pretty_title
108 if request.post? && @page.update_attributes(params[:wiki_page])
108 if request.post? && @page.update_attributes(params[:wiki_page])
109 flash[:notice] = l(:notice_successful_update)
109 flash[:notice] = l(:notice_successful_update)
110 redirect_to :action => 'index', :id => @project, :page => @page.title
110 redirect_to :action => 'index', :project_id => @project, :page => @page.title
111 end
111 end
112 end
112 end
113
113
114 def protect
114 def protect
115 @page.update_attribute :protected, params[:protected]
115 @page.update_attribute :protected, params[:protected]
116 redirect_to :action => 'index', :id => @project, :page => @page.title
116 redirect_to :action => 'index', :project_id => @project, :page => @page.title
117 end
117 end
118
118
119 # show page history
119 # show page history
120 def history
120 def history
121 @version_count = @page.content.versions.count
121 @version_count = @page.content.versions.count
122 @version_pages = Paginator.new self, @version_count, per_page_option, params['p']
122 @version_pages = Paginator.new self, @version_count, per_page_option, params['p']
123 # don't load text
123 # don't load text
124 @versions = @page.content.versions.find :all,
124 @versions = @page.content.versions.find :all,
125 :select => "id, author_id, comments, updated_on, version",
125 :select => "id, author_id, comments, updated_on, version",
126 :order => 'version DESC',
126 :order => 'version DESC',
127 :limit => @version_pages.items_per_page + 1,
127 :limit => @version_pages.items_per_page + 1,
128 :offset => @version_pages.current.offset
128 :offset => @version_pages.current.offset
129
129
130 render :layout => false if request.xhr?
130 render :layout => false if request.xhr?
131 end
131 end
132
132
133 def diff
133 def diff
134 @diff = @page.diff(params[:version], params[:version_from])
134 @diff = @page.diff(params[:version], params[:version_from])
135 render_404 unless @diff
135 render_404 unless @diff
136 end
136 end
137
137
138 def annotate
138 def annotate
139 @annotate = @page.annotate(params[:version])
139 @annotate = @page.annotate(params[:version])
140 render_404 unless @annotate
140 render_404 unless @annotate
141 end
141 end
142
142
143 # Removes a wiki page and its history
143 # Removes a wiki page and its history
144 # Children can be either set as root pages, removed or reassigned to another parent page
144 # Children can be either set as root pages, removed or reassigned to another parent page
145 def destroy
145 def destroy
146 return render_403 unless editable?
146 return render_403 unless editable?
147
147
148 @descendants_count = @page.descendants.size
148 @descendants_count = @page.descendants.size
149 if @descendants_count > 0
149 if @descendants_count > 0
150 case params[:todo]
150 case params[:todo]
151 when 'nullify'
151 when 'nullify'
152 # Nothing to do
152 # Nothing to do
153 when 'destroy'
153 when 'destroy'
154 # Removes all its descendants
154 # Removes all its descendants
155 @page.descendants.each(&:destroy)
155 @page.descendants.each(&:destroy)
156 when 'reassign'
156 when 'reassign'
157 # Reassign children to another parent page
157 # Reassign children to another parent page
158 reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i)
158 reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i)
159 return unless reassign_to
159 return unless reassign_to
160 @page.children.each do |child|
160 @page.children.each do |child|
161 child.update_attribute(:parent, reassign_to)
161 child.update_attribute(:parent, reassign_to)
162 end
162 end
163 else
163 else
164 @reassignable_to = @wiki.pages - @page.self_and_descendants
164 @reassignable_to = @wiki.pages - @page.self_and_descendants
165 return
165 return
166 end
166 end
167 end
167 end
168 @page.destroy
168 @page.destroy
169 redirect_to :action => 'page_index', :id => @project
169 redirect_to :action => 'page_index', :project_id => @project
170 end
170 end
171
171
172 # Export wiki to a single html file
172 # Export wiki to a single html file
173 def export
173 def export
174 if User.current.allowed_to?(:export_wiki_pages, @project)
174 if User.current.allowed_to?(:export_wiki_pages, @project)
175 @pages = @wiki.pages.find :all, :order => 'title'
175 @pages = @wiki.pages.find :all, :order => 'title'
176 export = render_to_string :action => 'export_multiple', :layout => false
176 export = render_to_string :action => 'export_multiple', :layout => false
177 send_data(export, :type => 'text/html', :filename => "wiki.html")
177 send_data(export, :type => 'text/html', :filename => "wiki.html")
178 else
178 else
179 redirect_to :action => 'index', :id => @project, :page => nil
179 redirect_to :action => 'index', :project_id => @project, :page => nil
180 end
180 end
181 end
181 end
182
182
183 def page_index
183 def page_index
184 load_pages_grouped_by_date_without_content
184 load_pages_grouped_by_date_without_content
185 end
185 end
186
186
187 def date_index
187 def date_index
188 load_pages_grouped_by_date_without_content
188 load_pages_grouped_by_date_without_content
189 end
189 end
190
190
191 def preview
191 def preview
192 page = @wiki.find_page(params[:page])
192 page = @wiki.find_page(params[:page])
193 # page is nil when previewing a new page
193 # page is nil when previewing a new page
194 return render_403 unless page.nil? || editable?(page)
194 return render_403 unless page.nil? || editable?(page)
195 if page
195 if page
196 @attachements = page.attachments
196 @attachements = page.attachments
197 @previewed = page.content
197 @previewed = page.content
198 end
198 end
199 @text = params[:content][:text]
199 @text = params[:content][:text]
200 render :partial => 'common/preview'
200 render :partial => 'common/preview'
201 end
201 end
202
202
203 def add_attachment
203 def add_attachment
204 return render_403 unless editable?
204 return render_403 unless editable?
205 attachments = Attachment.attach_files(@page, params[:attachments])
205 attachments = Attachment.attach_files(@page, params[:attachments])
206 render_attachment_warning_if_needed(@page)
206 render_attachment_warning_if_needed(@page)
207 redirect_to :action => 'index', :page => @page.title
207 redirect_to :action => 'index', :page => @page.title
208 end
208 end
209
209
210 private
210 private
211
211
212 def find_wiki
212 def find_wiki
213 @project = Project.find(params[:id])
213 @project = Project.find(params[:project_id])
214 @wiki = @project.wiki
214 @wiki = @project.wiki
215 render_404 unless @wiki
215 render_404 unless @wiki
216 rescue ActiveRecord::RecordNotFound
216 rescue ActiveRecord::RecordNotFound
217 render_404
217 render_404
218 end
218 end
219
219
220 # Finds the requested page and returns a 404 error if it doesn't exist
220 # Finds the requested page and returns a 404 error if it doesn't exist
221 def find_existing_page
221 def find_existing_page
222 @page = @wiki.find_page(params[:page])
222 @page = @wiki.find_page(params[:page])
223 render_404 if @page.nil?
223 render_404 if @page.nil?
224 end
224 end
225
225
226 # Returns true if the current user is allowed to edit the page, otherwise false
226 # Returns true if the current user is allowed to edit the page, otherwise false
227 def editable?(page = @page)
227 def editable?(page = @page)
228 page.editable_by?(User.current)
228 page.editable_by?(User.current)
229 end
229 end
230
230
231 # Returns the default content of a new wiki page
231 # Returns the default content of a new wiki page
232 def initial_page_content(page)
232 def initial_page_content(page)
233 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
233 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
234 extend helper unless self.instance_of?(helper)
234 extend helper unless self.instance_of?(helper)
235 helper.instance_method(:initial_page_content).bind(self).call(page)
235 helper.instance_method(:initial_page_content).bind(self).call(page)
236 end
236 end
237
237
238 # eager load information about last updates, without loading text
238 # eager load information about last updates, without loading text
239 def load_pages_grouped_by_date_without_content
239 def load_pages_grouped_by_date_without_content
240 @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
240 @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
241 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
241 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
242 :order => 'title'
242 :order => 'title'
243 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
243 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
244 @pages_by_parent_id = @pages.group_by(&:parent_id)
244 @pages_by_parent_id = @pages.group_by(&:parent_id)
245 end
245 end
246
246
247 end
247 end
@@ -1,850 +1,850
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 require 'forwardable'
18 require 'forwardable'
19 require 'cgi'
19 require 'cgi'
20
20
21 module ApplicationHelper
21 module ApplicationHelper
22 include Redmine::WikiFormatting::Macros::Definitions
22 include Redmine::WikiFormatting::Macros::Definitions
23 include Redmine::I18n
23 include Redmine::I18n
24 include GravatarHelper::PublicMethods
24 include GravatarHelper::PublicMethods
25
25
26 extend Forwardable
26 extend Forwardable
27 def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter
27 def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter
28
28
29 # Return true if user is authorized for controller/action, otherwise false
29 # Return true if user is authorized for controller/action, otherwise false
30 def authorize_for(controller, action)
30 def authorize_for(controller, action)
31 User.current.allowed_to?({:controller => controller, :action => action}, @project)
31 User.current.allowed_to?({:controller => controller, :action => action}, @project)
32 end
32 end
33
33
34 # Display a link if user is authorized
34 # Display a link if user is authorized
35 #
35 #
36 # @param [String] name Anchor text (passed to link_to)
36 # @param [String] name Anchor text (passed to link_to)
37 # @param [Hash] options Hash params. This will checked by authorize_for to see if the user is authorized
37 # @param [Hash] options Hash params. This will checked by authorize_for to see if the user is authorized
38 # @param [optional, Hash] html_options Options passed to link_to
38 # @param [optional, Hash] html_options Options passed to link_to
39 # @param [optional, Hash] parameters_for_method_reference Extra parameters for link_to
39 # @param [optional, Hash] parameters_for_method_reference Extra parameters for link_to
40 def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
40 def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
41 link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action])
41 link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action])
42 end
42 end
43
43
44 # Display a link to remote if user is authorized
44 # Display a link to remote if user is authorized
45 def link_to_remote_if_authorized(name, options = {}, html_options = nil)
45 def link_to_remote_if_authorized(name, options = {}, html_options = nil)
46 url = options[:url] || {}
46 url = options[:url] || {}
47 link_to_remote(name, options, html_options) if authorize_for(url[:controller] || params[:controller], url[:action])
47 link_to_remote(name, options, html_options) if authorize_for(url[:controller] || params[:controller], url[:action])
48 end
48 end
49
49
50 # Displays a link to user's account page if active
50 # Displays a link to user's account page if active
51 def link_to_user(user, options={})
51 def link_to_user(user, options={})
52 if user.is_a?(User)
52 if user.is_a?(User)
53 name = h(user.name(options[:format]))
53 name = h(user.name(options[:format]))
54 if user.active?
54 if user.active?
55 link_to name, :controller => 'users', :action => 'show', :id => user
55 link_to name, :controller => 'users', :action => 'show', :id => user
56 else
56 else
57 name
57 name
58 end
58 end
59 else
59 else
60 h(user.to_s)
60 h(user.to_s)
61 end
61 end
62 end
62 end
63
63
64 # Displays a link to +issue+ with its subject.
64 # Displays a link to +issue+ with its subject.
65 # Examples:
65 # Examples:
66 #
66 #
67 # link_to_issue(issue) # => Defect #6: This is the subject
67 # link_to_issue(issue) # => Defect #6: This is the subject
68 # link_to_issue(issue, :truncate => 6) # => Defect #6: This i...
68 # link_to_issue(issue, :truncate => 6) # => Defect #6: This i...
69 # link_to_issue(issue, :subject => false) # => Defect #6
69 # link_to_issue(issue, :subject => false) # => Defect #6
70 # link_to_issue(issue, :project => true) # => Foo - Defect #6
70 # link_to_issue(issue, :project => true) # => Foo - Defect #6
71 #
71 #
72 def link_to_issue(issue, options={})
72 def link_to_issue(issue, options={})
73 title = nil
73 title = nil
74 subject = nil
74 subject = nil
75 if options[:subject] == false
75 if options[:subject] == false
76 title = truncate(issue.subject, :length => 60)
76 title = truncate(issue.subject, :length => 60)
77 else
77 else
78 subject = issue.subject
78 subject = issue.subject
79 if options[:truncate]
79 if options[:truncate]
80 subject = truncate(subject, :length => options[:truncate])
80 subject = truncate(subject, :length => options[:truncate])
81 end
81 end
82 end
82 end
83 s = link_to "#{issue.tracker} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue},
83 s = link_to "#{issue.tracker} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue},
84 :class => issue.css_classes,
84 :class => issue.css_classes,
85 :title => title
85 :title => title
86 s << ": #{h subject}" if subject
86 s << ": #{h subject}" if subject
87 s = "#{h issue.project} - " + s if options[:project]
87 s = "#{h issue.project} - " + s if options[:project]
88 s
88 s
89 end
89 end
90
90
91 # Generates a link to an attachment.
91 # Generates a link to an attachment.
92 # Options:
92 # Options:
93 # * :text - Link text (default to attachment filename)
93 # * :text - Link text (default to attachment filename)
94 # * :download - Force download (default: false)
94 # * :download - Force download (default: false)
95 def link_to_attachment(attachment, options={})
95 def link_to_attachment(attachment, options={})
96 text = options.delete(:text) || attachment.filename
96 text = options.delete(:text) || attachment.filename
97 action = options.delete(:download) ? 'download' : 'show'
97 action = options.delete(:download) ? 'download' : 'show'
98
98
99 link_to(h(text), {:controller => 'attachments', :action => action, :id => attachment, :filename => attachment.filename }, options)
99 link_to(h(text), {:controller => 'attachments', :action => action, :id => attachment, :filename => attachment.filename }, options)
100 end
100 end
101
101
102 # Generates a link to a SCM revision
102 # Generates a link to a SCM revision
103 # Options:
103 # Options:
104 # * :text - Link text (default to the formatted revision)
104 # * :text - Link text (default to the formatted revision)
105 def link_to_revision(revision, project, options={})
105 def link_to_revision(revision, project, options={})
106 text = options.delete(:text) || format_revision(revision)
106 text = options.delete(:text) || format_revision(revision)
107
107
108 link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => revision}, :title => l(:label_revision_id, revision))
108 link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => revision}, :title => l(:label_revision_id, revision))
109 end
109 end
110
110
111 def link_to_project(project, options={})
111 def link_to_project(project, options={})
112 options[:class] ||= 'project'
112 options[:class] ||= 'project'
113 link_to(h(project), {:controller => 'projects', :action => 'show', :id => project}, :class => options[:class])
113 link_to(h(project), {:controller => 'projects', :action => 'show', :id => project}, :class => options[:class])
114 end
114 end
115
115
116 # Generates a link to a project if active
116 # Generates a link to a project if active
117 # Examples:
117 # Examples:
118 #
118 #
119 # link_to_project(project) # => link to the specified project overview
119 # link_to_project(project) # => link to the specified project overview
120 # link_to_project(project, :action=>'settings') # => link to project settings
120 # link_to_project(project, :action=>'settings') # => link to project settings
121 # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options
121 # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options
122 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview)
122 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview)
123 #
123 #
124 def link_to_project(project, options={}, html_options = nil)
124 def link_to_project(project, options={}, html_options = nil)
125 if project.active?
125 if project.active?
126 url = {:controller => 'projects', :action => 'show', :id => project}.merge(options)
126 url = {:controller => 'projects', :action => 'show', :id => project}.merge(options)
127 link_to(h(project), url, html_options)
127 link_to(h(project), url, html_options)
128 else
128 else
129 h(project)
129 h(project)
130 end
130 end
131 end
131 end
132
132
133 def toggle_link(name, id, options={})
133 def toggle_link(name, id, options={})
134 onclick = "Element.toggle('#{id}'); "
134 onclick = "Element.toggle('#{id}'); "
135 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
135 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
136 onclick << "return false;"
136 onclick << "return false;"
137 link_to(name, "#", :onclick => onclick)
137 link_to(name, "#", :onclick => onclick)
138 end
138 end
139
139
140 def image_to_function(name, function, html_options = {})
140 def image_to_function(name, function, html_options = {})
141 html_options.symbolize_keys!
141 html_options.symbolize_keys!
142 tag(:input, html_options.merge({
142 tag(:input, html_options.merge({
143 :type => "image", :src => image_path(name),
143 :type => "image", :src => image_path(name),
144 :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
144 :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
145 }))
145 }))
146 end
146 end
147
147
148 def prompt_to_remote(name, text, param, url, html_options = {})
148 def prompt_to_remote(name, text, param, url, html_options = {})
149 html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;"
149 html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;"
150 link_to name, {}, html_options
150 link_to name, {}, html_options
151 end
151 end
152
152
153 def format_activity_title(text)
153 def format_activity_title(text)
154 h(truncate_single_line(text, :length => 100))
154 h(truncate_single_line(text, :length => 100))
155 end
155 end
156
156
157 def format_activity_day(date)
157 def format_activity_day(date)
158 date == Date.today ? l(:label_today).titleize : format_date(date)
158 date == Date.today ? l(:label_today).titleize : format_date(date)
159 end
159 end
160
160
161 def format_activity_description(text)
161 def format_activity_description(text)
162 h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />")
162 h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />")
163 end
163 end
164
164
165 def format_version_name(version)
165 def format_version_name(version)
166 if version.project == @project
166 if version.project == @project
167 h(version)
167 h(version)
168 else
168 else
169 h("#{version.project} - #{version}")
169 h("#{version.project} - #{version}")
170 end
170 end
171 end
171 end
172
172
173 def due_date_distance_in_words(date)
173 def due_date_distance_in_words(date)
174 if date
174 if date
175 l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date))
175 l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date))
176 end
176 end
177 end
177 end
178
178
179 def render_page_hierarchy(pages, node=nil)
179 def render_page_hierarchy(pages, node=nil)
180 content = ''
180 content = ''
181 if pages[node]
181 if pages[node]
182 content << "<ul class=\"pages-hierarchy\">\n"
182 content << "<ul class=\"pages-hierarchy\">\n"
183 pages[node].each do |page|
183 pages[node].each do |page|
184 content << "<li>"
184 content << "<li>"
185 content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'index', :id => page.project, :page => page.title},
185 content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'index', :project_id => page.project, :page => page.title},
186 :title => (page.respond_to?(:updated_on) ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))
186 :title => (page.respond_to?(:updated_on) ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))
187 content << "\n" + render_page_hierarchy(pages, page.id) if pages[page.id]
187 content << "\n" + render_page_hierarchy(pages, page.id) if pages[page.id]
188 content << "</li>\n"
188 content << "</li>\n"
189 end
189 end
190 content << "</ul>\n"
190 content << "</ul>\n"
191 end
191 end
192 content
192 content
193 end
193 end
194
194
195 # Renders flash messages
195 # Renders flash messages
196 def render_flash_messages
196 def render_flash_messages
197 s = ''
197 s = ''
198 flash.each do |k,v|
198 flash.each do |k,v|
199 s << content_tag('div', v, :class => "flash #{k}")
199 s << content_tag('div', v, :class => "flash #{k}")
200 end
200 end
201 s
201 s
202 end
202 end
203
203
204 # Renders tabs and their content
204 # Renders tabs and their content
205 def render_tabs(tabs)
205 def render_tabs(tabs)
206 if tabs.any?
206 if tabs.any?
207 render :partial => 'common/tabs', :locals => {:tabs => tabs}
207 render :partial => 'common/tabs', :locals => {:tabs => tabs}
208 else
208 else
209 content_tag 'p', l(:label_no_data), :class => "nodata"
209 content_tag 'p', l(:label_no_data), :class => "nodata"
210 end
210 end
211 end
211 end
212
212
213 # Renders the project quick-jump box
213 # Renders the project quick-jump box
214 def render_project_jump_box
214 def render_project_jump_box
215 # Retrieve them now to avoid a COUNT query
215 # Retrieve them now to avoid a COUNT query
216 projects = User.current.projects.all
216 projects = User.current.projects.all
217 if projects.any?
217 if projects.any?
218 s = '<select onchange="if (this.value != \'\') { window.location = this.value; }">' +
218 s = '<select onchange="if (this.value != \'\') { window.location = this.value; }">' +
219 "<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
219 "<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
220 '<option value="" disabled="disabled">---</option>'
220 '<option value="" disabled="disabled">---</option>'
221 s << project_tree_options_for_select(projects, :selected => @project) do |p|
221 s << project_tree_options_for_select(projects, :selected => @project) do |p|
222 { :value => url_for(:controller => 'projects', :action => 'show', :id => p, :jump => current_menu_item) }
222 { :value => url_for(:controller => 'projects', :action => 'show', :id => p, :jump => current_menu_item) }
223 end
223 end
224 s << '</select>'
224 s << '</select>'
225 s
225 s
226 end
226 end
227 end
227 end
228
228
229 def project_tree_options_for_select(projects, options = {})
229 def project_tree_options_for_select(projects, options = {})
230 s = ''
230 s = ''
231 project_tree(projects) do |project, level|
231 project_tree(projects) do |project, level|
232 name_prefix = (level > 0 ? ('&nbsp;' * 2 * level + '&#187; ') : '')
232 name_prefix = (level > 0 ? ('&nbsp;' * 2 * level + '&#187; ') : '')
233 tag_options = {:value => project.id}
233 tag_options = {:value => project.id}
234 if project == options[:selected] || (options[:selected].respond_to?(:include?) && options[:selected].include?(project))
234 if project == options[:selected] || (options[:selected].respond_to?(:include?) && options[:selected].include?(project))
235 tag_options[:selected] = 'selected'
235 tag_options[:selected] = 'selected'
236 else
236 else
237 tag_options[:selected] = nil
237 tag_options[:selected] = nil
238 end
238 end
239 tag_options.merge!(yield(project)) if block_given?
239 tag_options.merge!(yield(project)) if block_given?
240 s << content_tag('option', name_prefix + h(project), tag_options)
240 s << content_tag('option', name_prefix + h(project), tag_options)
241 end
241 end
242 s
242 s
243 end
243 end
244
244
245 # Yields the given block for each project with its level in the tree
245 # Yields the given block for each project with its level in the tree
246 def project_tree(projects, &block)
246 def project_tree(projects, &block)
247 ancestors = []
247 ancestors = []
248 projects.sort_by(&:lft).each do |project|
248 projects.sort_by(&:lft).each do |project|
249 while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
249 while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
250 ancestors.pop
250 ancestors.pop
251 end
251 end
252 yield project, ancestors.size
252 yield project, ancestors.size
253 ancestors << project
253 ancestors << project
254 end
254 end
255 end
255 end
256
256
257 def project_nested_ul(projects, &block)
257 def project_nested_ul(projects, &block)
258 s = ''
258 s = ''
259 if projects.any?
259 if projects.any?
260 ancestors = []
260 ancestors = []
261 projects.sort_by(&:lft).each do |project|
261 projects.sort_by(&:lft).each do |project|
262 if (ancestors.empty? || project.is_descendant_of?(ancestors.last))
262 if (ancestors.empty? || project.is_descendant_of?(ancestors.last))
263 s << "<ul>\n"
263 s << "<ul>\n"
264 else
264 else
265 ancestors.pop
265 ancestors.pop
266 s << "</li>"
266 s << "</li>"
267 while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
267 while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
268 ancestors.pop
268 ancestors.pop
269 s << "</ul></li>\n"
269 s << "</ul></li>\n"
270 end
270 end
271 end
271 end
272 s << "<li>"
272 s << "<li>"
273 s << yield(project).to_s
273 s << yield(project).to_s
274 ancestors << project
274 ancestors << project
275 end
275 end
276 s << ("</li></ul>\n" * ancestors.size)
276 s << ("</li></ul>\n" * ancestors.size)
277 end
277 end
278 s
278 s
279 end
279 end
280
280
281 def principals_check_box_tags(name, principals)
281 def principals_check_box_tags(name, principals)
282 s = ''
282 s = ''
283 principals.sort.each do |principal|
283 principals.sort.each do |principal|
284 s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n"
284 s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n"
285 end
285 end
286 s
286 s
287 end
287 end
288
288
289 # Truncates and returns the string as a single line
289 # Truncates and returns the string as a single line
290 def truncate_single_line(string, *args)
290 def truncate_single_line(string, *args)
291 truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ')
291 truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ')
292 end
292 end
293
293
294 # Truncates at line break after 250 characters or options[:length]
294 # Truncates at line break after 250 characters or options[:length]
295 def truncate_lines(string, options={})
295 def truncate_lines(string, options={})
296 length = options[:length] || 250
296 length = options[:length] || 250
297 if string.to_s =~ /\A(.{#{length}}.*?)$/m
297 if string.to_s =~ /\A(.{#{length}}.*?)$/m
298 "#{$1}..."
298 "#{$1}..."
299 else
299 else
300 string
300 string
301 end
301 end
302 end
302 end
303
303
304 def html_hours(text)
304 def html_hours(text)
305 text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>')
305 text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>')
306 end
306 end
307
307
308 def authoring(created, author, options={})
308 def authoring(created, author, options={})
309 l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created))
309 l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created))
310 end
310 end
311
311
312 def time_tag(time)
312 def time_tag(time)
313 text = distance_of_time_in_words(Time.now, time)
313 text = distance_of_time_in_words(Time.now, time)
314 if @project
314 if @project
315 link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => time.to_date}, :title => format_time(time))
315 link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => time.to_date}, :title => format_time(time))
316 else
316 else
317 content_tag('acronym', text, :title => format_time(time))
317 content_tag('acronym', text, :title => format_time(time))
318 end
318 end
319 end
319 end
320
320
321 def syntax_highlight(name, content)
321 def syntax_highlight(name, content)
322 Redmine::SyntaxHighlighting.highlight_by_filename(content, name)
322 Redmine::SyntaxHighlighting.highlight_by_filename(content, name)
323 end
323 end
324
324
325 def to_path_param(path)
325 def to_path_param(path)
326 path.to_s.split(%r{[/\\]}).select {|p| !p.blank?}
326 path.to_s.split(%r{[/\\]}).select {|p| !p.blank?}
327 end
327 end
328
328
329 def pagination_links_full(paginator, count=nil, options={})
329 def pagination_links_full(paginator, count=nil, options={})
330 page_param = options.delete(:page_param) || :page
330 page_param = options.delete(:page_param) || :page
331 per_page_links = options.delete(:per_page_links)
331 per_page_links = options.delete(:per_page_links)
332 url_param = params.dup
332 url_param = params.dup
333 # don't reuse query params if filters are present
333 # don't reuse query params if filters are present
334 url_param.merge!(:fields => nil, :values => nil, :operators => nil) if url_param.delete(:set_filter)
334 url_param.merge!(:fields => nil, :values => nil, :operators => nil) if url_param.delete(:set_filter)
335
335
336 html = ''
336 html = ''
337 if paginator.current.previous
337 if paginator.current.previous
338 html << link_to_remote_content_update('&#171; ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' '
338 html << link_to_remote_content_update('&#171; ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' '
339 end
339 end
340
340
341 html << (pagination_links_each(paginator, options) do |n|
341 html << (pagination_links_each(paginator, options) do |n|
342 link_to_remote_content_update(n.to_s, url_param.merge(page_param => n))
342 link_to_remote_content_update(n.to_s, url_param.merge(page_param => n))
343 end || '')
343 end || '')
344
344
345 if paginator.current.next
345 if paginator.current.next
346 html << ' ' + link_to_remote_content_update((l(:label_next) + ' &#187;'), url_param.merge(page_param => paginator.current.next))
346 html << ' ' + link_to_remote_content_update((l(:label_next) + ' &#187;'), url_param.merge(page_param => paginator.current.next))
347 end
347 end
348
348
349 unless count.nil?
349 unless count.nil?
350 html << " (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})"
350 html << " (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})"
351 if per_page_links != false && links = per_page_links(paginator.items_per_page)
351 if per_page_links != false && links = per_page_links(paginator.items_per_page)
352 html << " | #{links}"
352 html << " | #{links}"
353 end
353 end
354 end
354 end
355
355
356 html
356 html
357 end
357 end
358
358
359 def per_page_links(selected=nil)
359 def per_page_links(selected=nil)
360 url_param = params.dup
360 url_param = params.dup
361 url_param.clear if url_param.has_key?(:set_filter)
361 url_param.clear if url_param.has_key?(:set_filter)
362
362
363 links = Setting.per_page_options_array.collect do |n|
363 links = Setting.per_page_options_array.collect do |n|
364 n == selected ? n : link_to_remote(n, {:update => "content",
364 n == selected ? n : link_to_remote(n, {:update => "content",
365 :url => params.dup.merge(:per_page => n),
365 :url => params.dup.merge(:per_page => n),
366 :method => :get},
366 :method => :get},
367 {:href => url_for(url_param.merge(:per_page => n))})
367 {:href => url_for(url_param.merge(:per_page => n))})
368 end
368 end
369 links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil
369 links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil
370 end
370 end
371
371
372 def reorder_links(name, url)
372 def reorder_links(name, url)
373 link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), url.merge({"#{name}[move_to]" => 'highest'}), :method => :post, :title => l(:label_sort_highest)) +
373 link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), url.merge({"#{name}[move_to]" => 'highest'}), :method => :post, :title => l(:label_sort_highest)) +
374 link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), url.merge({"#{name}[move_to]" => 'higher'}), :method => :post, :title => l(:label_sort_higher)) +
374 link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), url.merge({"#{name}[move_to]" => 'higher'}), :method => :post, :title => l(:label_sort_higher)) +
375 link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), url.merge({"#{name}[move_to]" => 'lower'}), :method => :post, :title => l(:label_sort_lower)) +
375 link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), url.merge({"#{name}[move_to]" => 'lower'}), :method => :post, :title => l(:label_sort_lower)) +
376 link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), url.merge({"#{name}[move_to]" => 'lowest'}), :method => :post, :title => l(:label_sort_lowest))
376 link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), url.merge({"#{name}[move_to]" => 'lowest'}), :method => :post, :title => l(:label_sort_lowest))
377 end
377 end
378
378
379 def breadcrumb(*args)
379 def breadcrumb(*args)
380 elements = args.flatten
380 elements = args.flatten
381 elements.any? ? content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb') : nil
381 elements.any? ? content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb') : nil
382 end
382 end
383
383
384 def other_formats_links(&block)
384 def other_formats_links(&block)
385 concat('<p class="other-formats">' + l(:label_export_to))
385 concat('<p class="other-formats">' + l(:label_export_to))
386 yield Redmine::Views::OtherFormatsBuilder.new(self)
386 yield Redmine::Views::OtherFormatsBuilder.new(self)
387 concat('</p>')
387 concat('</p>')
388 end
388 end
389
389
390 def page_header_title
390 def page_header_title
391 if @project.nil? || @project.new_record?
391 if @project.nil? || @project.new_record?
392 h(Setting.app_title)
392 h(Setting.app_title)
393 else
393 else
394 b = []
394 b = []
395 ancestors = (@project.root? ? [] : @project.ancestors.visible)
395 ancestors = (@project.root? ? [] : @project.ancestors.visible)
396 if ancestors.any?
396 if ancestors.any?
397 root = ancestors.shift
397 root = ancestors.shift
398 b << link_to_project(root, {:jump => current_menu_item}, :class => 'root')
398 b << link_to_project(root, {:jump => current_menu_item}, :class => 'root')
399 if ancestors.size > 2
399 if ancestors.size > 2
400 b << '&#8230;'
400 b << '&#8230;'
401 ancestors = ancestors[-2, 2]
401 ancestors = ancestors[-2, 2]
402 end
402 end
403 b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') }
403 b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') }
404 end
404 end
405 b << h(@project)
405 b << h(@project)
406 b.join(' &#187; ')
406 b.join(' &#187; ')
407 end
407 end
408 end
408 end
409
409
410 def html_title(*args)
410 def html_title(*args)
411 if args.empty?
411 if args.empty?
412 title = []
412 title = []
413 title << @project.name if @project
413 title << @project.name if @project
414 title += @html_title if @html_title
414 title += @html_title if @html_title
415 title << Setting.app_title
415 title << Setting.app_title
416 title.select {|t| !t.blank? }.join(' - ')
416 title.select {|t| !t.blank? }.join(' - ')
417 else
417 else
418 @html_title ||= []
418 @html_title ||= []
419 @html_title += args
419 @html_title += args
420 end
420 end
421 end
421 end
422
422
423 # Returns the theme, controller name, and action as css classes for the
423 # Returns the theme, controller name, and action as css classes for the
424 # HTML body.
424 # HTML body.
425 def body_css_classes
425 def body_css_classes
426 css = []
426 css = []
427 if theme = Redmine::Themes.theme(Setting.ui_theme)
427 if theme = Redmine::Themes.theme(Setting.ui_theme)
428 css << 'theme-' + theme.name
428 css << 'theme-' + theme.name
429 end
429 end
430
430
431 css << 'controller-' + params[:controller]
431 css << 'controller-' + params[:controller]
432 css << 'action-' + params[:action]
432 css << 'action-' + params[:action]
433 css.join(' ')
433 css.join(' ')
434 end
434 end
435
435
436 def accesskey(s)
436 def accesskey(s)
437 Redmine::AccessKeys.key_for s
437 Redmine::AccessKeys.key_for s
438 end
438 end
439
439
440 # Formats text according to system settings.
440 # Formats text according to system settings.
441 # 2 ways to call this method:
441 # 2 ways to call this method:
442 # * with a String: textilizable(text, options)
442 # * with a String: textilizable(text, options)
443 # * with an object and one of its attribute: textilizable(issue, :description, options)
443 # * with an object and one of its attribute: textilizable(issue, :description, options)
444 def textilizable(*args)
444 def textilizable(*args)
445 options = args.last.is_a?(Hash) ? args.pop : {}
445 options = args.last.is_a?(Hash) ? args.pop : {}
446 case args.size
446 case args.size
447 when 1
447 when 1
448 obj = options[:object]
448 obj = options[:object]
449 text = args.shift
449 text = args.shift
450 when 2
450 when 2
451 obj = args.shift
451 obj = args.shift
452 attr = args.shift
452 attr = args.shift
453 text = obj.send(attr).to_s
453 text = obj.send(attr).to_s
454 else
454 else
455 raise ArgumentError, 'invalid arguments to textilizable'
455 raise ArgumentError, 'invalid arguments to textilizable'
456 end
456 end
457 return '' if text.blank?
457 return '' if text.blank?
458 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
458 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
459 only_path = options.delete(:only_path) == false ? false : true
459 only_path = options.delete(:only_path) == false ? false : true
460
460
461 text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) }
461 text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) }
462
462
463 parse_non_pre_blocks(text) do |text|
463 parse_non_pre_blocks(text) do |text|
464 [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name|
464 [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name|
465 send method_name, text, project, obj, attr, only_path, options
465 send method_name, text, project, obj, attr, only_path, options
466 end
466 end
467 end
467 end
468 end
468 end
469
469
470 def parse_non_pre_blocks(text)
470 def parse_non_pre_blocks(text)
471 s = StringScanner.new(text)
471 s = StringScanner.new(text)
472 tags = []
472 tags = []
473 parsed = ''
473 parsed = ''
474 while !s.eos?
474 while !s.eos?
475 s.scan(/(.*?)(<(\/)?(pre|code)(.*?)>|\z)/im)
475 s.scan(/(.*?)(<(\/)?(pre|code)(.*?)>|\z)/im)
476 text, full_tag, closing, tag = s[1], s[2], s[3], s[4]
476 text, full_tag, closing, tag = s[1], s[2], s[3], s[4]
477 if tags.empty?
477 if tags.empty?
478 yield text
478 yield text
479 end
479 end
480 parsed << text
480 parsed << text
481 if tag
481 if tag
482 if closing
482 if closing
483 if tags.last == tag.downcase
483 if tags.last == tag.downcase
484 tags.pop
484 tags.pop
485 end
485 end
486 else
486 else
487 tags << tag.downcase
487 tags << tag.downcase
488 end
488 end
489 parsed << full_tag
489 parsed << full_tag
490 end
490 end
491 end
491 end
492 # Close any non closing tags
492 # Close any non closing tags
493 while tag = tags.pop
493 while tag = tags.pop
494 parsed << "</#{tag}>"
494 parsed << "</#{tag}>"
495 end
495 end
496 parsed
496 parsed
497 end
497 end
498
498
499 def parse_inline_attachments(text, project, obj, attr, only_path, options)
499 def parse_inline_attachments(text, project, obj, attr, only_path, options)
500 # when using an image link, try to use an attachment, if possible
500 # when using an image link, try to use an attachment, if possible
501 if options[:attachments] || (obj && obj.respond_to?(:attachments))
501 if options[:attachments] || (obj && obj.respond_to?(:attachments))
502 attachments = nil
502 attachments = nil
503 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m|
503 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m|
504 filename, ext, alt, alttext = $1.downcase, $2, $3, $4
504 filename, ext, alt, alttext = $1.downcase, $2, $3, $4
505 attachments ||= (options[:attachments] || obj.attachments).sort_by(&:created_on).reverse
505 attachments ||= (options[:attachments] || obj.attachments).sort_by(&:created_on).reverse
506 # search for the picture in attachments
506 # search for the picture in attachments
507 if found = attachments.detect { |att| att.filename.downcase == filename }
507 if found = attachments.detect { |att| att.filename.downcase == filename }
508 image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found
508 image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found
509 desc = found.description.to_s.gsub('"', '')
509 desc = found.description.to_s.gsub('"', '')
510 if !desc.blank? && alttext.blank?
510 if !desc.blank? && alttext.blank?
511 alt = " title=\"#{desc}\" alt=\"#{desc}\""
511 alt = " title=\"#{desc}\" alt=\"#{desc}\""
512 end
512 end
513 "src=\"#{image_url}\"#{alt}"
513 "src=\"#{image_url}\"#{alt}"
514 else
514 else
515 m
515 m
516 end
516 end
517 end
517 end
518 end
518 end
519 end
519 end
520
520
521 # Wiki links
521 # Wiki links
522 #
522 #
523 # Examples:
523 # Examples:
524 # [[mypage]]
524 # [[mypage]]
525 # [[mypage|mytext]]
525 # [[mypage|mytext]]
526 # wiki links can refer other project wikis, using project name or identifier:
526 # wiki links can refer other project wikis, using project name or identifier:
527 # [[project:]] -> wiki starting page
527 # [[project:]] -> wiki starting page
528 # [[project:|mytext]]
528 # [[project:|mytext]]
529 # [[project:mypage]]
529 # [[project:mypage]]
530 # [[project:mypage|mytext]]
530 # [[project:mypage|mytext]]
531 def parse_wiki_links(text, project, obj, attr, only_path, options)
531 def parse_wiki_links(text, project, obj, attr, only_path, options)
532 text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m|
532 text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m|
533 link_project = project
533 link_project = project
534 esc, all, page, title = $1, $2, $3, $5
534 esc, all, page, title = $1, $2, $3, $5
535 if esc.nil?
535 if esc.nil?
536 if page =~ /^([^\:]+)\:(.*)$/
536 if page =~ /^([^\:]+)\:(.*)$/
537 link_project = Project.find_by_name($1) || Project.find_by_identifier($1)
537 link_project = Project.find_by_name($1) || Project.find_by_identifier($1)
538 page = $2
538 page = $2
539 title ||= $1 if page.blank?
539 title ||= $1 if page.blank?
540 end
540 end
541
541
542 if link_project && link_project.wiki
542 if link_project && link_project.wiki
543 # extract anchor
543 # extract anchor
544 anchor = nil
544 anchor = nil
545 if page =~ /^(.+?)\#(.+)$/
545 if page =~ /^(.+?)\#(.+)$/
546 page, anchor = $1, $2
546 page, anchor = $1, $2
547 end
547 end
548 # check if page exists
548 # check if page exists
549 wiki_page = link_project.wiki.find_page(page)
549 wiki_page = link_project.wiki.find_page(page)
550 url = case options[:wiki_links]
550 url = case options[:wiki_links]
551 when :local; "#{title}.html"
551 when :local; "#{title}.html"
552 when :anchor; "##{title}" # used for single-file wiki export
552 when :anchor; "##{title}" # used for single-file wiki export
553 else
553 else
554 url_for(:only_path => only_path, :controller => 'wiki', :action => 'index', :id => link_project, :page => Wiki.titleize(page), :anchor => anchor)
554 url_for(:only_path => only_path, :controller => 'wiki', :action => 'index', :project_id => link_project, :page => Wiki.titleize(page), :anchor => anchor)
555 end
555 end
556 link_to((title || page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new')))
556 link_to((title || page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new')))
557 else
557 else
558 # project or wiki doesn't exist
558 # project or wiki doesn't exist
559 all
559 all
560 end
560 end
561 else
561 else
562 all
562 all
563 end
563 end
564 end
564 end
565 end
565 end
566
566
567 # Redmine links
567 # Redmine links
568 #
568 #
569 # Examples:
569 # Examples:
570 # Issues:
570 # Issues:
571 # #52 -> Link to issue #52
571 # #52 -> Link to issue #52
572 # Changesets:
572 # Changesets:
573 # r52 -> Link to revision 52
573 # r52 -> Link to revision 52
574 # commit:a85130f -> Link to scmid starting with a85130f
574 # commit:a85130f -> Link to scmid starting with a85130f
575 # Documents:
575 # Documents:
576 # document#17 -> Link to document with id 17
576 # document#17 -> Link to document with id 17
577 # document:Greetings -> Link to the document with title "Greetings"
577 # document:Greetings -> Link to the document with title "Greetings"
578 # document:"Some document" -> Link to the document with title "Some document"
578 # document:"Some document" -> Link to the document with title "Some document"
579 # Versions:
579 # Versions:
580 # version#3 -> Link to version with id 3
580 # version#3 -> Link to version with id 3
581 # version:1.0.0 -> Link to version named "1.0.0"
581 # version:1.0.0 -> Link to version named "1.0.0"
582 # version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
582 # version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
583 # Attachments:
583 # Attachments:
584 # attachment:file.zip -> Link to the attachment of the current object named file.zip
584 # attachment:file.zip -> Link to the attachment of the current object named file.zip
585 # Source files:
585 # Source files:
586 # source:some/file -> Link to the file located at /some/file in the project's repository
586 # source:some/file -> Link to the file located at /some/file in the project's repository
587 # source:some/file@52 -> Link to the file's revision 52
587 # source:some/file@52 -> Link to the file's revision 52
588 # source:some/file#L120 -> Link to line 120 of the file
588 # source:some/file#L120 -> Link to line 120 of the file
589 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
589 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
590 # export:some/file -> Force the download of the file
590 # export:some/file -> Force the download of the file
591 # Forum messages:
591 # Forum messages:
592 # message#1218 -> Link to message with id 1218
592 # message#1218 -> Link to message with id 1218
593 def parse_redmine_links(text, project, obj, attr, only_path, options)
593 def parse_redmine_links(text, project, obj, attr, only_path, options)
594 text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(attachment|document|version|commit|source|export|message|project)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|,|\s|\]|<|$)}) do |m|
594 text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(attachment|document|version|commit|source|export|message|project)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|,|\s|\]|<|$)}) do |m|
595 leading, esc, prefix, sep, identifier = $1, $2, $3, $5 || $7, $6 || $8
595 leading, esc, prefix, sep, identifier = $1, $2, $3, $5 || $7, $6 || $8
596 link = nil
596 link = nil
597 if esc.nil?
597 if esc.nil?
598 if prefix.nil? && sep == 'r'
598 if prefix.nil? && sep == 'r'
599 if project && (changeset = project.changesets.find_by_revision(identifier))
599 if project && (changeset = project.changesets.find_by_revision(identifier))
600 link = link_to("r#{identifier}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
600 link = link_to("r#{identifier}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
601 :class => 'changeset',
601 :class => 'changeset',
602 :title => truncate_single_line(changeset.comments, :length => 100))
602 :title => truncate_single_line(changeset.comments, :length => 100))
603 end
603 end
604 elsif sep == '#'
604 elsif sep == '#'
605 oid = identifier.to_i
605 oid = identifier.to_i
606 case prefix
606 case prefix
607 when nil
607 when nil
608 if issue = Issue.visible.find_by_id(oid, :include => :status)
608 if issue = Issue.visible.find_by_id(oid, :include => :status)
609 link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid},
609 link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid},
610 :class => issue.css_classes,
610 :class => issue.css_classes,
611 :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
611 :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
612 end
612 end
613 when 'document'
613 when 'document'
614 if document = Document.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
614 if document = Document.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
615 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
615 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
616 :class => 'document'
616 :class => 'document'
617 end
617 end
618 when 'version'
618 when 'version'
619 if version = Version.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
619 if version = Version.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
620 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
620 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
621 :class => 'version'
621 :class => 'version'
622 end
622 end
623 when 'message'
623 when 'message'
624 if message = Message.find_by_id(oid, :include => [:parent, {:board => :project}], :conditions => Project.visible_by(User.current))
624 if message = Message.find_by_id(oid, :include => [:parent, {:board => :project}], :conditions => Project.visible_by(User.current))
625 link = link_to h(truncate(message.subject, :length => 60)), {:only_path => only_path,
625 link = link_to h(truncate(message.subject, :length => 60)), {:only_path => only_path,
626 :controller => 'messages',
626 :controller => 'messages',
627 :action => 'show',
627 :action => 'show',
628 :board_id => message.board,
628 :board_id => message.board,
629 :id => message.root,
629 :id => message.root,
630 :anchor => (message.parent ? "message-#{message.id}" : nil)},
630 :anchor => (message.parent ? "message-#{message.id}" : nil)},
631 :class => 'message'
631 :class => 'message'
632 end
632 end
633 when 'project'
633 when 'project'
634 if p = Project.visible.find_by_id(oid)
634 if p = Project.visible.find_by_id(oid)
635 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
635 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
636 end
636 end
637 end
637 end
638 elsif sep == ':'
638 elsif sep == ':'
639 # removes the double quotes if any
639 # removes the double quotes if any
640 name = identifier.gsub(%r{^"(.*)"$}, "\\1")
640 name = identifier.gsub(%r{^"(.*)"$}, "\\1")
641 case prefix
641 case prefix
642 when 'document'
642 when 'document'
643 if project && document = project.documents.find_by_title(name)
643 if project && document = project.documents.find_by_title(name)
644 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
644 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
645 :class => 'document'
645 :class => 'document'
646 end
646 end
647 when 'version'
647 when 'version'
648 if project && version = project.versions.find_by_name(name)
648 if project && version = project.versions.find_by_name(name)
649 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
649 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
650 :class => 'version'
650 :class => 'version'
651 end
651 end
652 when 'commit'
652 when 'commit'
653 if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"]))
653 if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"]))
654 link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
654 link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
655 :class => 'changeset',
655 :class => 'changeset',
656 :title => truncate_single_line(changeset.comments, :length => 100)
656 :title => truncate_single_line(changeset.comments, :length => 100)
657 end
657 end
658 when 'source', 'export'
658 when 'source', 'export'
659 if project && project.repository
659 if project && project.repository
660 name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
660 name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
661 path, rev, anchor = $1, $3, $5
661 path, rev, anchor = $1, $3, $5
662 link = link_to h("#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project,
662 link = link_to h("#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project,
663 :path => to_path_param(path),
663 :path => to_path_param(path),
664 :rev => rev,
664 :rev => rev,
665 :anchor => anchor,
665 :anchor => anchor,
666 :format => (prefix == 'export' ? 'raw' : nil)},
666 :format => (prefix == 'export' ? 'raw' : nil)},
667 :class => (prefix == 'export' ? 'source download' : 'source')
667 :class => (prefix == 'export' ? 'source download' : 'source')
668 end
668 end
669 when 'attachment'
669 when 'attachment'
670 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
670 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
671 if attachments && attachment = attachments.detect {|a| a.filename == name }
671 if attachments && attachment = attachments.detect {|a| a.filename == name }
672 link = link_to h(attachment.filename), {:only_path => only_path, :controller => 'attachments', :action => 'download', :id => attachment},
672 link = link_to h(attachment.filename), {:only_path => only_path, :controller => 'attachments', :action => 'download', :id => attachment},
673 :class => 'attachment'
673 :class => 'attachment'
674 end
674 end
675 when 'project'
675 when 'project'
676 if p = Project.visible.find(:first, :conditions => ["identifier = :s OR LOWER(name) = :s", {:s => name.downcase}])
676 if p = Project.visible.find(:first, :conditions => ["identifier = :s OR LOWER(name) = :s", {:s => name.downcase}])
677 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
677 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
678 end
678 end
679 end
679 end
680 end
680 end
681 end
681 end
682 leading + (link || "#{prefix}#{sep}#{identifier}")
682 leading + (link || "#{prefix}#{sep}#{identifier}")
683 end
683 end
684 end
684 end
685
685
686 # Same as Rails' simple_format helper without using paragraphs
686 # Same as Rails' simple_format helper without using paragraphs
687 def simple_format_without_paragraph(text)
687 def simple_format_without_paragraph(text)
688 text.to_s.
688 text.to_s.
689 gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
689 gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
690 gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
690 gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
691 gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
691 gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
692 end
692 end
693
693
694 def lang_options_for_select(blank=true)
694 def lang_options_for_select(blank=true)
695 (blank ? [["(auto)", ""]] : []) +
695 (blank ? [["(auto)", ""]] : []) +
696 valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.last <=> y.last }
696 valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.last <=> y.last }
697 end
697 end
698
698
699 def label_tag_for(name, option_tags = nil, options = {})
699 def label_tag_for(name, option_tags = nil, options = {})
700 label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
700 label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
701 content_tag("label", label_text)
701 content_tag("label", label_text)
702 end
702 end
703
703
704 def labelled_tabular_form_for(name, object, options, &proc)
704 def labelled_tabular_form_for(name, object, options, &proc)
705 options[:html] ||= {}
705 options[:html] ||= {}
706 options[:html][:class] = 'tabular' unless options[:html].has_key?(:class)
706 options[:html][:class] = 'tabular' unless options[:html].has_key?(:class)
707 form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
707 form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
708 end
708 end
709
709
710 def back_url_hidden_field_tag
710 def back_url_hidden_field_tag
711 back_url = params[:back_url] || request.env['HTTP_REFERER']
711 back_url = params[:back_url] || request.env['HTTP_REFERER']
712 back_url = CGI.unescape(back_url.to_s)
712 back_url = CGI.unescape(back_url.to_s)
713 hidden_field_tag('back_url', CGI.escape(back_url)) unless back_url.blank?
713 hidden_field_tag('back_url', CGI.escape(back_url)) unless back_url.blank?
714 end
714 end
715
715
716 def check_all_links(form_name)
716 def check_all_links(form_name)
717 link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
717 link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
718 " | " +
718 " | " +
719 link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
719 link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
720 end
720 end
721
721
722 def progress_bar(pcts, options={})
722 def progress_bar(pcts, options={})
723 pcts = [pcts, pcts] unless pcts.is_a?(Array)
723 pcts = [pcts, pcts] unless pcts.is_a?(Array)
724 pcts = pcts.collect(&:round)
724 pcts = pcts.collect(&:round)
725 pcts[1] = pcts[1] - pcts[0]
725 pcts[1] = pcts[1] - pcts[0]
726 pcts << (100 - pcts[1] - pcts[0])
726 pcts << (100 - pcts[1] - pcts[0])
727 width = options[:width] || '100px;'
727 width = options[:width] || '100px;'
728 legend = options[:legend] || ''
728 legend = options[:legend] || ''
729 content_tag('table',
729 content_tag('table',
730 content_tag('tr',
730 content_tag('tr',
731 (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : '') +
731 (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : '') +
732 (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : '') +
732 (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : '') +
733 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : '')
733 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : '')
734 ), :class => 'progress', :style => "width: #{width};") +
734 ), :class => 'progress', :style => "width: #{width};") +
735 content_tag('p', legend, :class => 'pourcent')
735 content_tag('p', legend, :class => 'pourcent')
736 end
736 end
737
737
738 def checked_image(checked=true)
738 def checked_image(checked=true)
739 if checked
739 if checked
740 image_tag 'toggle_check.png'
740 image_tag 'toggle_check.png'
741 end
741 end
742 end
742 end
743
743
744 def context_menu(url)
744 def context_menu(url)
745 unless @context_menu_included
745 unless @context_menu_included
746 content_for :header_tags do
746 content_for :header_tags do
747 javascript_include_tag('context_menu') +
747 javascript_include_tag('context_menu') +
748 stylesheet_link_tag('context_menu')
748 stylesheet_link_tag('context_menu')
749 end
749 end
750 if l(:direction) == 'rtl'
750 if l(:direction) == 'rtl'
751 content_for :header_tags do
751 content_for :header_tags do
752 stylesheet_link_tag('context_menu_rtl')
752 stylesheet_link_tag('context_menu_rtl')
753 end
753 end
754 end
754 end
755 @context_menu_included = true
755 @context_menu_included = true
756 end
756 end
757 javascript_tag "new ContextMenu('#{ url_for(url) }')"
757 javascript_tag "new ContextMenu('#{ url_for(url) }')"
758 end
758 end
759
759
760 def context_menu_link(name, url, options={})
760 def context_menu_link(name, url, options={})
761 options[:class] ||= ''
761 options[:class] ||= ''
762 if options.delete(:selected)
762 if options.delete(:selected)
763 options[:class] << ' icon-checked disabled'
763 options[:class] << ' icon-checked disabled'
764 options[:disabled] = true
764 options[:disabled] = true
765 end
765 end
766 if options.delete(:disabled)
766 if options.delete(:disabled)
767 options.delete(:method)
767 options.delete(:method)
768 options.delete(:confirm)
768 options.delete(:confirm)
769 options.delete(:onclick)
769 options.delete(:onclick)
770 options[:class] << ' disabled'
770 options[:class] << ' disabled'
771 url = '#'
771 url = '#'
772 end
772 end
773 link_to name, url, options
773 link_to name, url, options
774 end
774 end
775
775
776 def calendar_for(field_id)
776 def calendar_for(field_id)
777 include_calendar_headers_tags
777 include_calendar_headers_tags
778 image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
778 image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
779 javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
779 javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
780 end
780 end
781
781
782 def include_calendar_headers_tags
782 def include_calendar_headers_tags
783 unless @calendar_headers_tags_included
783 unless @calendar_headers_tags_included
784 @calendar_headers_tags_included = true
784 @calendar_headers_tags_included = true
785 content_for :header_tags do
785 content_for :header_tags do
786 start_of_week = case Setting.start_of_week.to_i
786 start_of_week = case Setting.start_of_week.to_i
787 when 1
787 when 1
788 'Calendar._FD = 1;' # Monday
788 'Calendar._FD = 1;' # Monday
789 when 7
789 when 7
790 'Calendar._FD = 0;' # Sunday
790 'Calendar._FD = 0;' # Sunday
791 else
791 else
792 '' # use language
792 '' # use language
793 end
793 end
794
794
795 javascript_include_tag('calendar/calendar') +
795 javascript_include_tag('calendar/calendar') +
796 javascript_include_tag("calendar/lang/calendar-#{current_language.to_s.downcase}.js") +
796 javascript_include_tag("calendar/lang/calendar-#{current_language.to_s.downcase}.js") +
797 javascript_tag(start_of_week) +
797 javascript_tag(start_of_week) +
798 javascript_include_tag('calendar/calendar-setup') +
798 javascript_include_tag('calendar/calendar-setup') +
799 stylesheet_link_tag('calendar')
799 stylesheet_link_tag('calendar')
800 end
800 end
801 end
801 end
802 end
802 end
803
803
804 def content_for(name, content = nil, &block)
804 def content_for(name, content = nil, &block)
805 @has_content ||= {}
805 @has_content ||= {}
806 @has_content[name] = true
806 @has_content[name] = true
807 super(name, content, &block)
807 super(name, content, &block)
808 end
808 end
809
809
810 def has_content?(name)
810 def has_content?(name)
811 (@has_content && @has_content[name]) || false
811 (@has_content && @has_content[name]) || false
812 end
812 end
813
813
814 # Returns the avatar image tag for the given +user+ if avatars are enabled
814 # Returns the avatar image tag for the given +user+ if avatars are enabled
815 # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <joe@foo.bar>')
815 # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <joe@foo.bar>')
816 def avatar(user, options = { })
816 def avatar(user, options = { })
817 if Setting.gravatar_enabled?
817 if Setting.gravatar_enabled?
818 options.merge!({:ssl => (defined?(request) && request.ssl?), :default => Setting.gravatar_default})
818 options.merge!({:ssl => (defined?(request) && request.ssl?), :default => Setting.gravatar_default})
819 email = nil
819 email = nil
820 if user.respond_to?(:mail)
820 if user.respond_to?(:mail)
821 email = user.mail
821 email = user.mail
822 elsif user.to_s =~ %r{<(.+?)>}
822 elsif user.to_s =~ %r{<(.+?)>}
823 email = $1
823 email = $1
824 end
824 end
825 return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil
825 return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil
826 else
826 else
827 ''
827 ''
828 end
828 end
829 end
829 end
830
830
831 def favicon
831 def favicon
832 "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />"
832 "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />"
833 end
833 end
834
834
835 private
835 private
836
836
837 def wiki_helper
837 def wiki_helper
838 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
838 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
839 extend helper
839 extend helper
840 return self
840 return self
841 end
841 end
842
842
843 def link_to_remote_content_update(text, url_params)
843 def link_to_remote_content_update(text, url_params)
844 link_to_remote(text,
844 link_to_remote(text,
845 {:url => url_params, :method => :get, :update => 'content', :complete => 'window.scrollTo(0,0)'},
845 {:url => url_params, :method => :get, :update => 'content', :complete => 'window.scrollTo(0,0)'},
846 {:href => url_for(:params => url_params)}
846 {:href => url_for(:params => url_params)}
847 )
847 )
848 end
848 end
849
849
850 end
850 end
@@ -1,32 +1,32
1 <div class="contextual">
1 <div class="contextual">
2 <%= link_to(l(:button_edit), {:action => 'edit', :page => @page.title}, :class => 'icon icon-edit') %>
2 <%= link_to(l(:button_edit), {:action => 'edit', :page => @page.title}, :class => 'icon icon-edit') %>
3 <%= link_to(l(:label_history), {:action => 'history', :page => @page.title}, :class => 'icon icon-history') %>
3 <%= link_to(l(:label_history), {:action => 'history', :page => @page.title}, :class => 'icon icon-history') %>
4 </div>
4 </div>
5
5
6 <h2><%= @page.pretty_title %></h2>
6 <h2><%= @page.pretty_title %></h2>
7
7
8 <p>
8 <p>
9 <%= l(:label_version) %> <%= link_to @annotate.content.version, :action => 'index', :page => @page.title, :version => @annotate.content.version %>
9 <%= l(:label_version) %> <%= link_to @annotate.content.version, :action => 'index', :page => @page.title, :version => @annotate.content.version %>
10 <em>(<%= @annotate.content.author ? @annotate.content.author.name : "anonyme" %>, <%= format_time(@annotate.content.updated_on) %>)</em>
10 <em>(<%= @annotate.content.author ? @annotate.content.author.name : "anonyme" %>, <%= format_time(@annotate.content.updated_on) %>)</em>
11 </p>
11 </p>
12
12
13 <% colors = Hash.new {|k,v| k[v] = (k.size % 12) } %>
13 <% colors = Hash.new {|k,v| k[v] = (k.size % 12) } %>
14
14
15 <table class="filecontent annotate">
15 <table class="filecontent annotate">
16 <tbody>
16 <tbody>
17 <% line_num = 1 %>
17 <% line_num = 1 %>
18 <% @annotate.lines.each do |line| -%>
18 <% @annotate.lines.each do |line| -%>
19 <tr class="bloc-<%= colors[line[0]] %>">
19 <tr class="bloc-<%= colors[line[0]] %>">
20 <th class="line-num"><%= line_num %></th>
20 <th class="line-num"><%= line_num %></th>
21 <td class="revision"><%= link_to line[0], :controller => 'wiki', :action => 'index', :id => @project, :page => @page.title, :version => line[0] %></td>
21 <td class="revision"><%= link_to line[0], :controller => 'wiki', :action => 'index', :project_id => @project, :page => @page.title, :version => line[0] %></td>
22 <td class="author"><%= h(line[1]) %></td>
22 <td class="author"><%= h(line[1]) %></td>
23 <td class="line-code"><pre><%=h line[2] %></pre></td>
23 <td class="line-code"><pre><%=h line[2] %></pre></td>
24 </tr>
24 </tr>
25 <% line_num += 1 %>
25 <% line_num += 1 %>
26 <% end -%>
26 <% end -%>
27 </tbody>
27 </tbody>
28 </table>
28 </table>
29
29
30 <% content_for :header_tags do %>
30 <% content_for :header_tags do %>
31 <%= stylesheet_link_tag 'scm' %>
31 <%= stylesheet_link_tag 'scm' %>
32 <% end %>
32 <% end %>
@@ -1,19 +1,19
1 <h2><%=h @page.pretty_title %></h2>
1 <h2><%=h @page.pretty_title %></h2>
2
2
3 <% form_tag({}) do %>
3 <% form_tag({}) do %>
4 <div class="box">
4 <div class="box">
5 <p><strong><%= l(:text_wiki_page_destroy_question, :descendants => @descendants_count) %></strong></p>
5 <p><strong><%= l(:text_wiki_page_destroy_question, :descendants => @descendants_count) %></strong></p>
6 <p><label><%= radio_button_tag 'todo', 'nullify', true %> <%= l(:text_wiki_page_nullify_children) %></label><br />
6 <p><label><%= radio_button_tag 'todo', 'nullify', true %> <%= l(:text_wiki_page_nullify_children) %></label><br />
7 <label><%= radio_button_tag 'todo', 'destroy', false %> <%= l(:text_wiki_page_destroy_children) %></label>
7 <label><%= radio_button_tag 'todo', 'destroy', false %> <%= l(:text_wiki_page_destroy_children) %></label>
8 <% if @reassignable_to.any? %>
8 <% if @reassignable_to.any? %>
9 <br />
9 <br />
10 <label><%= radio_button_tag 'todo', 'reassign', false %> <%= l(:text_wiki_page_reassign_children) %></label>:
10 <label><%= radio_button_tag 'todo', 'reassign', false %> <%= l(:text_wiki_page_reassign_children) %></label>:
11 <%= select_tag 'reassign_to_id', wiki_page_options_for_select(@reassignable_to),
11 <%= select_tag 'reassign_to_id', wiki_page_options_for_select(@reassignable_to),
12 :onclick => "$('todo_reassign').checked = true;" %>
12 :onclick => "$('todo_reassign').checked = true;" %>
13 <% end %>
13 <% end %>
14 </p>
14 </p>
15 </div>
15 </div>
16
16
17 <%= submit_tag l(:button_apply) %>
17 <%= submit_tag l(:button_apply) %>
18 <%= link_to l(:button_cancel), :controller => 'wiki', :action => 'index', :id => @project, :page => @page.title %>
18 <%= link_to l(:button_cancel), :controller => 'wiki', :action => 'index', :project_id => @project, :page => @page.title %>
19 <% end %>
19 <% end %>
@@ -1,28 +1,28
1 <h2><%=h @page.pretty_title %></h2>
1 <h2><%=h @page.pretty_title %></h2>
2
2
3 <% form_for :content, @content, :url => {:action => 'edit', :page => @page.title}, :html => {:multipart => true, :id => 'wiki_form'} do |f| %>
3 <% form_for :content, @content, :url => {:action => 'edit', :page => @page.title}, :html => {:multipart => true, :id => 'wiki_form'} do |f| %>
4 <%= f.hidden_field :version %>
4 <%= f.hidden_field :version %>
5 <%= error_messages_for 'content' %>
5 <%= error_messages_for 'content' %>
6
6
7 <p><%= f.text_area :text, :cols => 100, :rows => 25, :class => 'wiki-edit', :accesskey => accesskey(:edit) %></p>
7 <p><%= f.text_area :text, :cols => 100, :rows => 25, :class => 'wiki-edit', :accesskey => accesskey(:edit) %></p>
8 <p><label><%= l(:field_comments) %></label><br /><%= f.text_field :comments, :size => 120 %></p>
8 <p><label><%= l(:field_comments) %></label><br /><%= f.text_field :comments, :size => 120 %></p>
9 <p><label><%=l(:label_attachment_plural)%></label><br /><%= render :partial => 'attachments/form' %></p>
9 <p><label><%=l(:label_attachment_plural)%></label><br /><%= render :partial => 'attachments/form' %></p>
10
10
11 <p><%= submit_tag l(:button_save) %>
11 <p><%= submit_tag l(:button_save) %>
12 <%= link_to_remote l(:label_preview),
12 <%= link_to_remote l(:label_preview),
13 { :url => { :controller => 'wiki', :action => 'preview', :id => @project, :page => @page.title },
13 { :url => { :controller => 'wiki', :action => 'preview', :project_id => @project, :page => @page.title },
14 :method => 'post',
14 :method => 'post',
15 :update => 'preview',
15 :update => 'preview',
16 :with => "Form.serialize('wiki_form')",
16 :with => "Form.serialize('wiki_form')",
17 :complete => "Element.scrollTo('preview')"
17 :complete => "Element.scrollTo('preview')"
18 }, :accesskey => accesskey(:preview) %></p>
18 }, :accesskey => accesskey(:preview) %></p>
19 <%= wikitoolbar_for 'content_text' %>
19 <%= wikitoolbar_for 'content_text' %>
20 <% end %>
20 <% end %>
21
21
22 <div id="preview" class="wiki"></div>
22 <div id="preview" class="wiki"></div>
23
23
24 <% content_for :header_tags do %>
24 <% content_for :header_tags do %>
25 <%= stylesheet_link_tag 'scm' %>
25 <%= stylesheet_link_tag 'scm' %>
26 <% end %>
26 <% end %>
27
27
28 <% html_title @page.pretty_title %>
28 <% html_title @page.pretty_title %>
@@ -1,35 +1,36
1 <h2><%= @page.pretty_title %></h2>
1 <h2><%= @page.pretty_title %></h2>
2
2
3 <h3><%= l(:label_history) %></h3>
3 <h3><%= l(:label_history) %></h3>
4
4
5 <% form_tag({:action => "diff"}, :method => :get) do %>
5 <% form_tag({:action => "diff"}, :method => :get) do %>
6 <%= hidden_field_tag('project_id', h(@project.to_param)) %>
6 <table class="list">
7 <table class="list">
7 <thead><tr>
8 <thead><tr>
8 <th>#</th>
9 <th>#</th>
9 <th></th>
10 <th></th>
10 <th></th>
11 <th></th>
11 <th><%= l(:field_updated_on) %></th>
12 <th><%= l(:field_updated_on) %></th>
12 <th><%= l(:field_author) %></th>
13 <th><%= l(:field_author) %></th>
13 <th><%= l(:field_comments) %></th>
14 <th><%= l(:field_comments) %></th>
14 <th></th>
15 <th></th>
15 </tr></thead>
16 </tr></thead>
16 <tbody>
17 <tbody>
17 <% show_diff = @versions.size > 1 %>
18 <% show_diff = @versions.size > 1 %>
18 <% line_num = 1 %>
19 <% line_num = 1 %>
19 <% @versions.each do |ver| %>
20 <% @versions.each do |ver| %>
20 <tr class="<%= cycle("odd", "even") %>">
21 <tr class="<%= cycle("odd", "even") %>">
21 <td class="id"><%= link_to ver.version, :action => 'index', :page => @page.title, :version => ver.version %></td>
22 <td class="id"><%= link_to ver.version, :action => 'index', :page => @page.title, :version => ver.version %></td>
22 <td class="checkbox"><%= radio_button_tag('version', ver.version, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < @versions.size) %></td>
23 <td class="checkbox"><%= radio_button_tag('version', ver.version, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < @versions.size) %></td>
23 <td class="checkbox"><%= radio_button_tag('version_from', ver.version, (line_num==2), :id => "cbto-#{line_num}") if show_diff && (line_num > 1) %></td>
24 <td class="checkbox"><%= radio_button_tag('version_from', ver.version, (line_num==2), :id => "cbto-#{line_num}") if show_diff && (line_num > 1) %></td>
24 <td align="center"><%= format_time(ver.updated_on) %></td>
25 <td align="center"><%= format_time(ver.updated_on) %></td>
25 <td><%= link_to_user ver.author %></td>
26 <td><%= link_to_user ver.author %></td>
26 <td><%=h ver.comments %></td>
27 <td><%=h ver.comments %></td>
27 <td align="center"><%= link_to l(:button_annotate), :action => 'annotate', :page => @page.title, :version => ver.version %></td>
28 <td align="center"><%= link_to l(:button_annotate), :action => 'annotate', :page => @page.title, :version => ver.version %></td>
28 </tr>
29 </tr>
29 <% line_num += 1 %>
30 <% line_num += 1 %>
30 <% end %>
31 <% end %>
31 </tbody>
32 </tbody>
32 </table>
33 </table>
33 <%= submit_tag l(:label_view_diff), :class => 'small' if show_diff %>
34 <%= submit_tag l(:label_view_diff), :class => 'small' if show_diff %>
34 <span class="pagination"><%= pagination_links_full @version_pages, @version_count, :page_param => :p %></span>
35 <span class="pagination"><%= pagination_links_full @version_pages, @version_count, :page_param => :p %></span>
35 <% end %>
36 <% end %>
@@ -1,248 +1,248
1 ActionController::Routing::Routes.draw do |map|
1 ActionController::Routing::Routes.draw do |map|
2 # Add your own custom routes here.
2 # Add your own custom routes here.
3 # The priority is based upon order of creation: first created -> highest priority.
3 # The priority is based upon order of creation: first created -> highest priority.
4
4
5 # Here's a sample route:
5 # Here's a sample route:
6 # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
6 # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
7 # Keep in mind you can assign values other than :controller and :action
7 # Keep in mind you can assign values other than :controller and :action
8
8
9 map.home '', :controller => 'welcome'
9 map.home '', :controller => 'welcome'
10
10
11 map.signin 'login', :controller => 'account', :action => 'login'
11 map.signin 'login', :controller => 'account', :action => 'login'
12 map.signout 'logout', :controller => 'account', :action => 'logout'
12 map.signout 'logout', :controller => 'account', :action => 'logout'
13
13
14 map.connect 'roles/workflow/:id/:role_id/:tracker_id', :controller => 'roles', :action => 'workflow'
14 map.connect 'roles/workflow/:id/:role_id/:tracker_id', :controller => 'roles', :action => 'workflow'
15 map.connect 'help/:ctrl/:page', :controller => 'help'
15 map.connect 'help/:ctrl/:page', :controller => 'help'
16
16
17 map.connect 'projects/:project_id/time_entries/report', :controller => 'time_entry_reports', :action => 'report'
17 map.connect 'projects/:project_id/time_entries/report', :controller => 'time_entry_reports', :action => 'report'
18 map.with_options :controller => 'time_entry_reports', :action => 'report',:conditions => {:method => :get} do |time_report|
18 map.with_options :controller => 'time_entry_reports', :action => 'report',:conditions => {:method => :get} do |time_report|
19 time_report.connect 'time_entries/report'
19 time_report.connect 'time_entries/report'
20 time_report.connect 'time_entries/report.:format'
20 time_report.connect 'time_entries/report.:format'
21 time_report.connect 'projects/:project_id/time_entries/report.:format'
21 time_report.connect 'projects/:project_id/time_entries/report.:format'
22 end
22 end
23
23
24 # TODO: wasteful since this is also nested under issues, projects, and projects/issues
24 # TODO: wasteful since this is also nested under issues, projects, and projects/issues
25 map.resources :time_entries, :controller => 'timelog'
25 map.resources :time_entries, :controller => 'timelog'
26
26
27 map.connect 'projects/:id/wiki', :controller => 'wikis', :action => 'edit', :conditions => {:method => :post}
27 map.connect 'projects/:id/wiki', :controller => 'wikis', :action => 'edit', :conditions => {:method => :post}
28 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :get}
28 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :get}
29 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :post}
29 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :post}
30 map.with_options :controller => 'wiki' do |wiki_routes|
30 map.with_options :controller => 'wiki' do |wiki_routes|
31 wiki_routes.with_options :conditions => {:method => :get} do |wiki_views|
31 wiki_routes.with_options :conditions => {:method => :get} do |wiki_views|
32 wiki_views.connect 'projects/:id/wiki/export', :action => 'export'
32 wiki_views.connect 'projects/:project_id/wiki/export', :action => 'export'
33 wiki_views.connect 'projects/:id/wiki/page_index', :action => 'page_index'
33 wiki_views.connect 'projects/:project_id/wiki/page_index', :action => 'page_index'
34 wiki_views.connect 'projects/:id/wiki/date_index', :action => 'date_index'
34 wiki_views.connect 'projects/:project_id/wiki/date_index', :action => 'date_index'
35 wiki_views.connect 'projects/:id/wiki/:page', :action => 'index', :page => nil
35 wiki_views.connect 'projects/:project_id/wiki/:page', :action => 'index', :page => nil
36 wiki_views.connect 'projects/:id/wiki/:page/edit', :action => 'edit'
36 wiki_views.connect 'projects/:project_id/wiki/:page/edit', :action => 'edit'
37 wiki_views.connect 'projects/:id/wiki/:page/rename', :action => 'rename'
37 wiki_views.connect 'projects/:project_id/wiki/:page/rename', :action => 'rename'
38 wiki_views.connect 'projects/:id/wiki/:page/history', :action => 'history'
38 wiki_views.connect 'projects/:project_id/wiki/:page/history', :action => 'history'
39 wiki_views.connect 'projects/:id/wiki/:page/diff/:version/vs/:version_from', :action => 'diff'
39 wiki_views.connect 'projects/:project_id/wiki/:page/diff/:version/vs/:version_from', :action => 'diff'
40 wiki_views.connect 'projects/:id/wiki/:page/annotate/:version', :action => 'annotate'
40 wiki_views.connect 'projects/:project_id/wiki/:page/annotate/:version', :action => 'annotate'
41 end
41 end
42
42
43 wiki_routes.connect 'projects/:id/wiki/:page/:action',
43 wiki_routes.connect 'projects/:project_id/wiki/:page/:action',
44 :action => /edit|rename|destroy|preview|protect/,
44 :action => /edit|rename|destroy|preview|protect/,
45 :conditions => {:method => :post}
45 :conditions => {:method => :post}
46 end
46 end
47
47
48 map.with_options :controller => 'messages' do |messages_routes|
48 map.with_options :controller => 'messages' do |messages_routes|
49 messages_routes.with_options :conditions => {:method => :get} do |messages_views|
49 messages_routes.with_options :conditions => {:method => :get} do |messages_views|
50 messages_views.connect 'boards/:board_id/topics/new', :action => 'new'
50 messages_views.connect 'boards/:board_id/topics/new', :action => 'new'
51 messages_views.connect 'boards/:board_id/topics/:id', :action => 'show'
51 messages_views.connect 'boards/:board_id/topics/:id', :action => 'show'
52 messages_views.connect 'boards/:board_id/topics/:id/edit', :action => 'edit'
52 messages_views.connect 'boards/:board_id/topics/:id/edit', :action => 'edit'
53 end
53 end
54 messages_routes.with_options :conditions => {:method => :post} do |messages_actions|
54 messages_routes.with_options :conditions => {:method => :post} do |messages_actions|
55 messages_actions.connect 'boards/:board_id/topics/new', :action => 'new'
55 messages_actions.connect 'boards/:board_id/topics/new', :action => 'new'
56 messages_actions.connect 'boards/:board_id/topics/:id/replies', :action => 'reply'
56 messages_actions.connect 'boards/:board_id/topics/:id/replies', :action => 'reply'
57 messages_actions.connect 'boards/:board_id/topics/:id/:action', :action => /edit|destroy/
57 messages_actions.connect 'boards/:board_id/topics/:id/:action', :action => /edit|destroy/
58 end
58 end
59 end
59 end
60
60
61 map.with_options :controller => 'boards' do |board_routes|
61 map.with_options :controller => 'boards' do |board_routes|
62 board_routes.with_options :conditions => {:method => :get} do |board_views|
62 board_routes.with_options :conditions => {:method => :get} do |board_views|
63 board_views.connect 'projects/:project_id/boards', :action => 'index'
63 board_views.connect 'projects/:project_id/boards', :action => 'index'
64 board_views.connect 'projects/:project_id/boards/new', :action => 'new'
64 board_views.connect 'projects/:project_id/boards/new', :action => 'new'
65 board_views.connect 'projects/:project_id/boards/:id', :action => 'show'
65 board_views.connect 'projects/:project_id/boards/:id', :action => 'show'
66 board_views.connect 'projects/:project_id/boards/:id.:format', :action => 'show'
66 board_views.connect 'projects/:project_id/boards/:id.:format', :action => 'show'
67 board_views.connect 'projects/:project_id/boards/:id/edit', :action => 'edit'
67 board_views.connect 'projects/:project_id/boards/:id/edit', :action => 'edit'
68 end
68 end
69 board_routes.with_options :conditions => {:method => :post} do |board_actions|
69 board_routes.with_options :conditions => {:method => :post} do |board_actions|
70 board_actions.connect 'projects/:project_id/boards', :action => 'new'
70 board_actions.connect 'projects/:project_id/boards', :action => 'new'
71 board_actions.connect 'projects/:project_id/boards/:id/:action', :action => /edit|destroy/
71 board_actions.connect 'projects/:project_id/boards/:id/:action', :action => /edit|destroy/
72 end
72 end
73 end
73 end
74
74
75 map.with_options :controller => 'documents' do |document_routes|
75 map.with_options :controller => 'documents' do |document_routes|
76 document_routes.with_options :conditions => {:method => :get} do |document_views|
76 document_routes.with_options :conditions => {:method => :get} do |document_views|
77 document_views.connect 'projects/:project_id/documents', :action => 'index'
77 document_views.connect 'projects/:project_id/documents', :action => 'index'
78 document_views.connect 'projects/:project_id/documents/new', :action => 'new'
78 document_views.connect 'projects/:project_id/documents/new', :action => 'new'
79 document_views.connect 'documents/:id', :action => 'show'
79 document_views.connect 'documents/:id', :action => 'show'
80 document_views.connect 'documents/:id/edit', :action => 'edit'
80 document_views.connect 'documents/:id/edit', :action => 'edit'
81 end
81 end
82 document_routes.with_options :conditions => {:method => :post} do |document_actions|
82 document_routes.with_options :conditions => {:method => :post} do |document_actions|
83 document_actions.connect 'projects/:project_id/documents', :action => 'new'
83 document_actions.connect 'projects/:project_id/documents', :action => 'new'
84 document_actions.connect 'documents/:id/:action', :action => /destroy|edit/
84 document_actions.connect 'documents/:id/:action', :action => /destroy|edit/
85 end
85 end
86 end
86 end
87
87
88 map.resources :issue_moves, :only => [:new, :create], :path_prefix => '/issues', :as => 'move'
88 map.resources :issue_moves, :only => [:new, :create], :path_prefix => '/issues', :as => 'move'
89
89
90 # Misc issue routes. TODO: move into resources
90 # Misc issue routes. TODO: move into resources
91 map.auto_complete_issues '/issues/auto_complete', :controller => 'auto_completes', :action => 'issues'
91 map.auto_complete_issues '/issues/auto_complete', :controller => 'auto_completes', :action => 'issues'
92 map.preview_issue '/issues/preview/:id', :controller => 'previews', :action => 'issue' # TODO: would look nicer as /issues/:id/preview
92 map.preview_issue '/issues/preview/:id', :controller => 'previews', :action => 'issue' # TODO: would look nicer as /issues/:id/preview
93 map.issues_context_menu '/issues/context_menu', :controller => 'context_menus', :action => 'issues'
93 map.issues_context_menu '/issues/context_menu', :controller => 'context_menus', :action => 'issues'
94 map.issue_changes '/issues/changes', :controller => 'journals', :action => 'index'
94 map.issue_changes '/issues/changes', :controller => 'journals', :action => 'index'
95 map.bulk_edit_issue 'issues/bulk_edit', :controller => 'issues', :action => 'bulk_edit', :conditions => { :method => :get }
95 map.bulk_edit_issue 'issues/bulk_edit', :controller => 'issues', :action => 'bulk_edit', :conditions => { :method => :get }
96 map.bulk_update_issue 'issues/bulk_edit', :controller => 'issues', :action => 'bulk_update', :conditions => { :method => :post }
96 map.bulk_update_issue 'issues/bulk_edit', :controller => 'issues', :action => 'bulk_update', :conditions => { :method => :post }
97 map.quoted_issue '/issues/:id/quoted', :controller => 'journals', :action => 'new', :id => /\d+/, :conditions => { :method => :post }
97 map.quoted_issue '/issues/:id/quoted', :controller => 'journals', :action => 'new', :id => /\d+/, :conditions => { :method => :post }
98 map.connect '/issues/:id/destroy', :controller => 'issues', :action => 'destroy', :conditions => { :method => :post } # legacy
98 map.connect '/issues/:id/destroy', :controller => 'issues', :action => 'destroy', :conditions => { :method => :post } # legacy
99
99
100 map.resource :gantt, :path_prefix => '/issues', :controller => 'gantts', :only => [:show, :update]
100 map.resource :gantt, :path_prefix => '/issues', :controller => 'gantts', :only => [:show, :update]
101 map.resource :gantt, :path_prefix => '/projects/:project_id/issues', :controller => 'gantts', :only => [:show, :update]
101 map.resource :gantt, :path_prefix => '/projects/:project_id/issues', :controller => 'gantts', :only => [:show, :update]
102 map.resource :calendar, :path_prefix => '/issues', :controller => 'calendars', :only => [:show, :update]
102 map.resource :calendar, :path_prefix => '/issues', :controller => 'calendars', :only => [:show, :update]
103 map.resource :calendar, :path_prefix => '/projects/:project_id/issues', :controller => 'calendars', :only => [:show, :update]
103 map.resource :calendar, :path_prefix => '/projects/:project_id/issues', :controller => 'calendars', :only => [:show, :update]
104
104
105 map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports|
105 map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports|
106 reports.connect 'projects/:id/issues/report', :action => 'issue_report'
106 reports.connect 'projects/:id/issues/report', :action => 'issue_report'
107 reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details'
107 reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details'
108 end
108 end
109
109
110 # Following two routes conflict with the resources because #index allows POST
110 # Following two routes conflict with the resources because #index allows POST
111 map.connect '/issues', :controller => 'issues', :action => 'index', :conditions => { :method => :post }
111 map.connect '/issues', :controller => 'issues', :action => 'index', :conditions => { :method => :post }
112 map.connect '/issues/create', :controller => 'issues', :action => 'index', :conditions => { :method => :post }
112 map.connect '/issues/create', :controller => 'issues', :action => 'index', :conditions => { :method => :post }
113
113
114 map.resources :issues, :member => { :edit => :post }, :collection => {} do |issues|
114 map.resources :issues, :member => { :edit => :post }, :collection => {} do |issues|
115 issues.resources :time_entries, :controller => 'timelog'
115 issues.resources :time_entries, :controller => 'timelog'
116 end
116 end
117
117
118 map.resources :issues, :path_prefix => '/projects/:project_id', :collection => { :create => :post } do |issues|
118 map.resources :issues, :path_prefix => '/projects/:project_id', :collection => { :create => :post } do |issues|
119 issues.resources :time_entries, :controller => 'timelog'
119 issues.resources :time_entries, :controller => 'timelog'
120 end
120 end
121
121
122 map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations|
122 map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations|
123 relations.connect 'issues/:issue_id/relations/:id', :action => 'new'
123 relations.connect 'issues/:issue_id/relations/:id', :action => 'new'
124 relations.connect 'issues/:issue_id/relations/:id/destroy', :action => 'destroy'
124 relations.connect 'issues/:issue_id/relations/:id/destroy', :action => 'destroy'
125 end
125 end
126
126
127 map.connect 'projects/:id/members/new', :controller => 'members', :action => 'new'
127 map.connect 'projects/:id/members/new', :controller => 'members', :action => 'new'
128
128
129 map.with_options :controller => 'users' do |users|
129 map.with_options :controller => 'users' do |users|
130 users.connect 'users/:id/edit/:tab', :action => 'edit', :tab => nil, :conditions => {:method => :get}
130 users.connect 'users/:id/edit/:tab', :action => 'edit', :tab => nil, :conditions => {:method => :get}
131
131
132 users.with_options :conditions => {:method => :post} do |user_actions|
132 users.with_options :conditions => {:method => :post} do |user_actions|
133 user_actions.connect 'users/:id/memberships', :action => 'edit_membership'
133 user_actions.connect 'users/:id/memberships', :action => 'edit_membership'
134 user_actions.connect 'users/:id/memberships/:membership_id', :action => 'edit_membership'
134 user_actions.connect 'users/:id/memberships/:membership_id', :action => 'edit_membership'
135 user_actions.connect 'users/:id/memberships/:membership_id/destroy', :action => 'destroy_membership'
135 user_actions.connect 'users/:id/memberships/:membership_id/destroy', :action => 'destroy_membership'
136 end
136 end
137 end
137 end
138
138
139 map.resources :users, :member => {
139 map.resources :users, :member => {
140 :edit_membership => :post,
140 :edit_membership => :post,
141 :destroy_membership => :post
141 :destroy_membership => :post
142 },
142 },
143 :except => [:destroy]
143 :except => [:destroy]
144
144
145 # For nice "roadmap" in the url for the index action
145 # For nice "roadmap" in the url for the index action
146 map.connect 'projects/:project_id/roadmap', :controller => 'versions', :action => 'index'
146 map.connect 'projects/:project_id/roadmap', :controller => 'versions', :action => 'index'
147
147
148 map.all_news 'news', :controller => 'news', :action => 'index'
148 map.all_news 'news', :controller => 'news', :action => 'index'
149 map.formatted_all_news 'news.:format', :controller => 'news', :action => 'index'
149 map.formatted_all_news 'news.:format', :controller => 'news', :action => 'index'
150 map.preview_news '/news/preview', :controller => 'previews', :action => 'news'
150 map.preview_news '/news/preview', :controller => 'previews', :action => 'news'
151 map.connect 'news/:id/comments', :controller => 'comments', :action => 'create', :conditions => {:method => :post}
151 map.connect 'news/:id/comments', :controller => 'comments', :action => 'create', :conditions => {:method => :post}
152 map.connect 'news/:id/comments/:comment_id', :controller => 'comments', :action => 'destroy', :conditions => {:method => :delete}
152 map.connect 'news/:id/comments/:comment_id', :controller => 'comments', :action => 'destroy', :conditions => {:method => :delete}
153
153
154 map.resources :projects, :member => {
154 map.resources :projects, :member => {
155 :copy => [:get, :post],
155 :copy => [:get, :post],
156 :settings => :get,
156 :settings => :get,
157 :modules => :post,
157 :modules => :post,
158 :archive => :post,
158 :archive => :post,
159 :unarchive => :post
159 :unarchive => :post
160 } do |project|
160 } do |project|
161 project.resource :project_enumerations, :as => 'enumerations', :only => [:update, :destroy]
161 project.resource :project_enumerations, :as => 'enumerations', :only => [:update, :destroy]
162 project.resources :files, :only => [:index, :new, :create]
162 project.resources :files, :only => [:index, :new, :create]
163 project.resources :versions, :collection => {:close_completed => :put}, :member => {:status_by => :post}
163 project.resources :versions, :collection => {:close_completed => :put}, :member => {:status_by => :post}
164 project.resources :news, :shallow => true
164 project.resources :news, :shallow => true
165 project.resources :time_entries, :controller => 'timelog', :path_prefix => 'projects/:project_id'
165 project.resources :time_entries, :controller => 'timelog', :path_prefix => 'projects/:project_id'
166
166
167
167
168 end
168 end
169
169
170 # Destroy uses a get request to prompt the user before the actual DELETE request
170 # Destroy uses a get request to prompt the user before the actual DELETE request
171 map.project_destroy_confirm 'projects/:id/destroy', :controller => 'projects', :action => 'destroy', :conditions => {:method => :get}
171 map.project_destroy_confirm 'projects/:id/destroy', :controller => 'projects', :action => 'destroy', :conditions => {:method => :get}
172
172
173 # TODO: port to be part of the resources route(s)
173 # TODO: port to be part of the resources route(s)
174 map.with_options :controller => 'projects' do |project_mapper|
174 map.with_options :controller => 'projects' do |project_mapper|
175 project_mapper.with_options :conditions => {:method => :get} do |project_views|
175 project_mapper.with_options :conditions => {:method => :get} do |project_views|
176 project_views.connect 'projects/:id/settings/:tab', :controller => 'projects', :action => 'settings'
176 project_views.connect 'projects/:id/settings/:tab', :controller => 'projects', :action => 'settings'
177 project_views.connect 'projects/:project_id/issues/:copy_from/copy', :controller => 'issues', :action => 'new'
177 project_views.connect 'projects/:project_id/issues/:copy_from/copy', :controller => 'issues', :action => 'new'
178 end
178 end
179 end
179 end
180
180
181 map.with_options :controller => 'activities', :action => 'index', :conditions => {:method => :get} do |activity|
181 map.with_options :controller => 'activities', :action => 'index', :conditions => {:method => :get} do |activity|
182 activity.connect 'projects/:id/activity'
182 activity.connect 'projects/:id/activity'
183 activity.connect 'projects/:id/activity.:format'
183 activity.connect 'projects/:id/activity.:format'
184 activity.connect 'activity', :id => nil
184 activity.connect 'activity', :id => nil
185 activity.connect 'activity.:format', :id => nil
185 activity.connect 'activity.:format', :id => nil
186 end
186 end
187
187
188
188
189 map.with_options :controller => 'issue_categories' do |categories|
189 map.with_options :controller => 'issue_categories' do |categories|
190 categories.connect 'projects/:project_id/issue_categories/new', :action => 'new'
190 categories.connect 'projects/:project_id/issue_categories/new', :action => 'new'
191 end
191 end
192
192
193 map.with_options :controller => 'repositories' do |repositories|
193 map.with_options :controller => 'repositories' do |repositories|
194 repositories.with_options :conditions => {:method => :get} do |repository_views|
194 repositories.with_options :conditions => {:method => :get} do |repository_views|
195 repository_views.connect 'projects/:id/repository', :action => 'show'
195 repository_views.connect 'projects/:id/repository', :action => 'show'
196 repository_views.connect 'projects/:id/repository/edit', :action => 'edit'
196 repository_views.connect 'projects/:id/repository/edit', :action => 'edit'
197 repository_views.connect 'projects/:id/repository/statistics', :action => 'stats'
197 repository_views.connect 'projects/:id/repository/statistics', :action => 'stats'
198 repository_views.connect 'projects/:id/repository/revisions', :action => 'revisions'
198 repository_views.connect 'projects/:id/repository/revisions', :action => 'revisions'
199 repository_views.connect 'projects/:id/repository/revisions.:format', :action => 'revisions'
199 repository_views.connect 'projects/:id/repository/revisions.:format', :action => 'revisions'
200 repository_views.connect 'projects/:id/repository/revisions/:rev', :action => 'revision'
200 repository_views.connect 'projects/:id/repository/revisions/:rev', :action => 'revision'
201 repository_views.connect 'projects/:id/repository/revisions/:rev/diff', :action => 'diff'
201 repository_views.connect 'projects/:id/repository/revisions/:rev/diff', :action => 'diff'
202 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format', :action => 'diff'
202 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format', :action => 'diff'
203 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path', :action => 'entry', :format => 'raw', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
203 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path', :action => 'entry', :format => 'raw', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
204 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
204 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
205 repository_views.connect 'projects/:id/repository/raw/*path', :action => 'entry', :format => 'raw'
205 repository_views.connect 'projects/:id/repository/raw/*path', :action => 'entry', :format => 'raw'
206 # TODO: why the following route is required?
206 # TODO: why the following route is required?
207 repository_views.connect 'projects/:id/repository/entry/*path', :action => 'entry'
207 repository_views.connect 'projects/:id/repository/entry/*path', :action => 'entry'
208 repository_views.connect 'projects/:id/repository/:action/*path'
208 repository_views.connect 'projects/:id/repository/:action/*path'
209 end
209 end
210
210
211 repositories.connect 'projects/:id/repository/:action', :conditions => {:method => :post}
211 repositories.connect 'projects/:id/repository/:action', :conditions => {:method => :post}
212 end
212 end
213
213
214 map.connect 'attachments/:id', :controller => 'attachments', :action => 'show', :id => /\d+/
214 map.connect 'attachments/:id', :controller => 'attachments', :action => 'show', :id => /\d+/
215 map.connect 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/
215 map.connect 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/
216 map.connect 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/
216 map.connect 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/
217
217
218 map.resources :groups
218 map.resources :groups
219
219
220 #left old routes at the bottom for backwards compat
220 #left old routes at the bottom for backwards compat
221 map.connect 'projects/:project_id/issues/:action', :controller => 'issues'
221 map.connect 'projects/:project_id/issues/:action', :controller => 'issues'
222 map.connect 'projects/:project_id/documents/:action', :controller => 'documents'
222 map.connect 'projects/:project_id/documents/:action', :controller => 'documents'
223 map.connect 'projects/:project_id/boards/:action/:id', :controller => 'boards'
223 map.connect 'projects/:project_id/boards/:action/:id', :controller => 'boards'
224 map.connect 'boards/:board_id/topics/:action/:id', :controller => 'messages'
224 map.connect 'boards/:board_id/topics/:action/:id', :controller => 'messages'
225 map.connect 'wiki/:id/:page/:action', :page => nil, :controller => 'wiki'
225 map.connect 'wiki/:id/:page/:action', :page => nil, :controller => 'wiki'
226 map.connect 'issues/:issue_id/relations/:action/:id', :controller => 'issue_relations'
226 map.connect 'issues/:issue_id/relations/:action/:id', :controller => 'issue_relations'
227 map.connect 'projects/:project_id/news/:action', :controller => 'news'
227 map.connect 'projects/:project_id/news/:action', :controller => 'news'
228 map.connect 'projects/:project_id/timelog/:action/:id', :controller => 'timelog', :project_id => /.+/
228 map.connect 'projects/:project_id/timelog/:action/:id', :controller => 'timelog', :project_id => /.+/
229 map.with_options :controller => 'repositories' do |omap|
229 map.with_options :controller => 'repositories' do |omap|
230 omap.repositories_show 'repositories/browse/:id/*path', :action => 'browse'
230 omap.repositories_show 'repositories/browse/:id/*path', :action => 'browse'
231 omap.repositories_changes 'repositories/changes/:id/*path', :action => 'changes'
231 omap.repositories_changes 'repositories/changes/:id/*path', :action => 'changes'
232 omap.repositories_diff 'repositories/diff/:id/*path', :action => 'diff'
232 omap.repositories_diff 'repositories/diff/:id/*path', :action => 'diff'
233 omap.repositories_entry 'repositories/entry/:id/*path', :action => 'entry'
233 omap.repositories_entry 'repositories/entry/:id/*path', :action => 'entry'
234 omap.repositories_entry 'repositories/annotate/:id/*path', :action => 'annotate'
234 omap.repositories_entry 'repositories/annotate/:id/*path', :action => 'annotate'
235 omap.connect 'repositories/revision/:id/:rev', :action => 'revision'
235 omap.connect 'repositories/revision/:id/:rev', :action => 'revision'
236 end
236 end
237
237
238 map.with_options :controller => 'sys' do |sys|
238 map.with_options :controller => 'sys' do |sys|
239 sys.connect 'sys/projects.:format', :action => 'projects', :conditions => {:method => :get}
239 sys.connect 'sys/projects.:format', :action => 'projects', :conditions => {:method => :get}
240 sys.connect 'sys/projects/:id/repository.:format', :action => 'create_project_repository', :conditions => {:method => :post}
240 sys.connect 'sys/projects/:id/repository.:format', :action => 'create_project_repository', :conditions => {:method => :post}
241 end
241 end
242
242
243 # Install the default route as the lowest priority.
243 # Install the default route as the lowest priority.
244 map.connect ':controller/:action/:id'
244 map.connect ':controller/:action/:id'
245 map.connect 'robots.txt', :controller => 'welcome', :action => 'robots'
245 map.connect 'robots.txt', :controller => 'welcome', :action => 'robots'
246 # Used for OpenID
246 # Used for OpenID
247 map.root :controller => 'account', :action => 'login'
247 map.root :controller => 'account', :action => 'login'
248 end
248 end
@@ -1,231 +1,231
1 require 'redmine/access_control'
1 require 'redmine/access_control'
2 require 'redmine/menu_manager'
2 require 'redmine/menu_manager'
3 require 'redmine/activity'
3 require 'redmine/activity'
4 require 'redmine/search'
4 require 'redmine/search'
5 require 'redmine/custom_field_format'
5 require 'redmine/custom_field_format'
6 require 'redmine/mime_type'
6 require 'redmine/mime_type'
7 require 'redmine/core_ext'
7 require 'redmine/core_ext'
8 require 'redmine/themes'
8 require 'redmine/themes'
9 require 'redmine/hook'
9 require 'redmine/hook'
10 require 'redmine/plugin'
10 require 'redmine/plugin'
11 require 'redmine/notifiable'
11 require 'redmine/notifiable'
12 require 'redmine/wiki_formatting'
12 require 'redmine/wiki_formatting'
13 require 'redmine/scm/base'
13 require 'redmine/scm/base'
14
14
15 begin
15 begin
16 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
16 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
17 rescue LoadError
17 rescue LoadError
18 # RMagick is not available
18 # RMagick is not available
19 end
19 end
20
20
21 if RUBY_VERSION < '1.9'
21 if RUBY_VERSION < '1.9'
22 require 'faster_csv'
22 require 'faster_csv'
23 else
23 else
24 require 'csv'
24 require 'csv'
25 FCSV = CSV
25 FCSV = CSV
26 end
26 end
27
27
28 Redmine::Scm::Base.add "Subversion"
28 Redmine::Scm::Base.add "Subversion"
29 Redmine::Scm::Base.add "Darcs"
29 Redmine::Scm::Base.add "Darcs"
30 Redmine::Scm::Base.add "Mercurial"
30 Redmine::Scm::Base.add "Mercurial"
31 Redmine::Scm::Base.add "Cvs"
31 Redmine::Scm::Base.add "Cvs"
32 Redmine::Scm::Base.add "Bazaar"
32 Redmine::Scm::Base.add "Bazaar"
33 Redmine::Scm::Base.add "Git"
33 Redmine::Scm::Base.add "Git"
34 Redmine::Scm::Base.add "Filesystem"
34 Redmine::Scm::Base.add "Filesystem"
35
35
36 Redmine::CustomFieldFormat.map do |fields|
36 Redmine::CustomFieldFormat.map do |fields|
37 fields.register Redmine::CustomFieldFormat.new('string', :label => :label_string, :order => 1)
37 fields.register Redmine::CustomFieldFormat.new('string', :label => :label_string, :order => 1)
38 fields.register Redmine::CustomFieldFormat.new('text', :label => :label_text, :order => 2)
38 fields.register Redmine::CustomFieldFormat.new('text', :label => :label_text, :order => 2)
39 fields.register Redmine::CustomFieldFormat.new('int', :label => :label_integer, :order => 3)
39 fields.register Redmine::CustomFieldFormat.new('int', :label => :label_integer, :order => 3)
40 fields.register Redmine::CustomFieldFormat.new('float', :label => :label_float, :order => 4)
40 fields.register Redmine::CustomFieldFormat.new('float', :label => :label_float, :order => 4)
41 fields.register Redmine::CustomFieldFormat.new('list', :label => :label_list, :order => 5)
41 fields.register Redmine::CustomFieldFormat.new('list', :label => :label_list, :order => 5)
42 fields.register Redmine::CustomFieldFormat.new('date', :label => :label_date, :order => 6)
42 fields.register Redmine::CustomFieldFormat.new('date', :label => :label_date, :order => 6)
43 fields.register Redmine::CustomFieldFormat.new('bool', :label => :label_boolean, :order => 7)
43 fields.register Redmine::CustomFieldFormat.new('bool', :label => :label_boolean, :order => 7)
44 end
44 end
45
45
46 # Permissions
46 # Permissions
47 Redmine::AccessControl.map do |map|
47 Redmine::AccessControl.map do |map|
48 map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true
48 map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true
49 map.permission :search_project, {:search => :index}, :public => true
49 map.permission :search_project, {:search => :index}, :public => true
50 map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin
50 map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin
51 map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member
51 map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member
52 map.permission :select_project_modules, {:projects => :modules}, :require => :member
52 map.permission :select_project_modules, {:projects => :modules}, :require => :member
53 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy, :autocomplete_for_member]}, :require => :member
53 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy, :autocomplete_for_member]}, :require => :member
54 map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
54 map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
55 map.permission :add_subprojects, {:projects => [:new, :create]}, :require => :member
55 map.permission :add_subprojects, {:projects => [:new, :create]}, :require => :member
56
56
57 map.project_module :issue_tracking do |map|
57 map.project_module :issue_tracking do |map|
58 # Issue categories
58 # Issue categories
59 map.permission :manage_categories, {:projects => :settings, :issue_categories => [:new, :edit, :destroy]}, :require => :member
59 map.permission :manage_categories, {:projects => :settings, :issue_categories => [:new, :edit, :destroy]}, :require => :member
60 # Issues
60 # Issues
61 map.permission :view_issues, {:issues => [:index, :show],
61 map.permission :view_issues, {:issues => [:index, :show],
62 :auto_complete => [:issues],
62 :auto_complete => [:issues],
63 :context_menus => [:issues],
63 :context_menus => [:issues],
64 :versions => [:index, :show, :status_by],
64 :versions => [:index, :show, :status_by],
65 :journals => :index,
65 :journals => :index,
66 :queries => :index,
66 :queries => :index,
67 :reports => [:issue_report, :issue_report_details]}
67 :reports => [:issue_report, :issue_report_details]}
68 map.permission :add_issues, {:issues => [:new, :create, :update_form]}
68 map.permission :add_issues, {:issues => [:new, :create, :update_form]}
69 map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]}
69 map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]}
70 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
70 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
71 map.permission :manage_subtasks, {}
71 map.permission :manage_subtasks, {}
72 map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new]}
72 map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new]}
73 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
73 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
74 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
74 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
75 map.permission :move_issues, {:issue_moves => [:new, :create]}, :require => :loggedin
75 map.permission :move_issues, {:issue_moves => [:new, :create]}, :require => :loggedin
76 map.permission :delete_issues, {:issues => :destroy}, :require => :member
76 map.permission :delete_issues, {:issues => :destroy}, :require => :member
77 # Queries
77 # Queries
78 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
78 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
79 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
79 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
80 # Watchers
80 # Watchers
81 map.permission :view_issue_watchers, {}
81 map.permission :view_issue_watchers, {}
82 map.permission :add_issue_watchers, {:watchers => :new}
82 map.permission :add_issue_watchers, {:watchers => :new}
83 map.permission :delete_issue_watchers, {:watchers => :destroy}
83 map.permission :delete_issue_watchers, {:watchers => :destroy}
84 end
84 end
85
85
86 map.project_module :time_tracking do |map|
86 map.project_module :time_tracking do |map|
87 map.permission :log_time, {:timelog => [:new, :create, :edit, :update]}, :require => :loggedin
87 map.permission :log_time, {:timelog => [:new, :create, :edit, :update]}, :require => :loggedin
88 map.permission :view_time_entries, :timelog => [:index], :time_entry_reports => [:report]
88 map.permission :view_time_entries, :timelog => [:index], :time_entry_reports => [:report]
89 map.permission :edit_time_entries, {:timelog => [:new, :create, :edit, :update, :destroy]}, :require => :member
89 map.permission :edit_time_entries, {:timelog => [:new, :create, :edit, :update, :destroy]}, :require => :member
90 map.permission :edit_own_time_entries, {:timelog => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
90 map.permission :edit_own_time_entries, {:timelog => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
91 map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
91 map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
92 end
92 end
93
93
94 map.project_module :news do |map|
94 map.project_module :news do |map|
95 map.permission :manage_news, {:news => [:new, :create, :edit, :update, :destroy], :comments => [:destroy]}, :require => :member
95 map.permission :manage_news, {:news => [:new, :create, :edit, :update, :destroy], :comments => [:destroy]}, :require => :member
96 map.permission :view_news, {:news => [:index, :show]}, :public => true
96 map.permission :view_news, {:news => [:index, :show]}, :public => true
97 map.permission :comment_news, {:comments => :create}
97 map.permission :comment_news, {:comments => :create}
98 end
98 end
99
99
100 map.project_module :documents do |map|
100 map.project_module :documents do |map|
101 map.permission :manage_documents, {:documents => [:new, :edit, :destroy, :add_attachment]}, :require => :loggedin
101 map.permission :manage_documents, {:documents => [:new, :edit, :destroy, :add_attachment]}, :require => :loggedin
102 map.permission :view_documents, :documents => [:index, :show, :download]
102 map.permission :view_documents, :documents => [:index, :show, :download]
103 end
103 end
104
104
105 map.project_module :files do |map|
105 map.project_module :files do |map|
106 map.permission :manage_files, {:files => [:new, :create]}, :require => :loggedin
106 map.permission :manage_files, {:files => [:new, :create]}, :require => :loggedin
107 map.permission :view_files, :files => :index, :versions => :download
107 map.permission :view_files, :files => :index, :versions => :download
108 end
108 end
109
109
110 map.project_module :wiki do |map|
110 map.project_module :wiki do |map|
111 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
111 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
112 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
112 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
113 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
113 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
114 map.permission :view_wiki_pages, :wiki => [:index, :special, :page_index, :date_index]
114 map.permission :view_wiki_pages, :wiki => [:index, :special, :page_index, :date_index]
115 map.permission :export_wiki_pages, :wiki => [:export]
115 map.permission :export_wiki_pages, :wiki => [:export]
116 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
116 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
117 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment]
117 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment]
118 map.permission :delete_wiki_pages_attachments, {}
118 map.permission :delete_wiki_pages_attachments, {}
119 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
119 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
120 end
120 end
121
121
122 map.project_module :repository do |map|
122 map.project_module :repository do |map|
123 map.permission :manage_repository, {:repositories => [:edit, :committers, :destroy]}, :require => :member
123 map.permission :manage_repository, {:repositories => [:edit, :committers, :destroy]}, :require => :member
124 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
124 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
125 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
125 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
126 map.permission :commit_access, {}
126 map.permission :commit_access, {}
127 end
127 end
128
128
129 map.project_module :boards do |map|
129 map.project_module :boards do |map|
130 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
130 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
131 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
131 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
132 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
132 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
133 map.permission :edit_messages, {:messages => :edit}, :require => :member
133 map.permission :edit_messages, {:messages => :edit}, :require => :member
134 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
134 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
135 map.permission :delete_messages, {:messages => :destroy}, :require => :member
135 map.permission :delete_messages, {:messages => :destroy}, :require => :member
136 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
136 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
137 end
137 end
138
138
139 map.project_module :calendar do |map|
139 map.project_module :calendar do |map|
140 map.permission :view_calendar, :calendars => [:show, :update]
140 map.permission :view_calendar, :calendars => [:show, :update]
141 end
141 end
142
142
143 map.project_module :gantt do |map|
143 map.project_module :gantt do |map|
144 map.permission :view_gantt, :gantts => [:show, :update]
144 map.permission :view_gantt, :gantts => [:show, :update]
145 end
145 end
146 end
146 end
147
147
148 Redmine::MenuManager.map :top_menu do |menu|
148 Redmine::MenuManager.map :top_menu do |menu|
149 menu.push :home, :home_path
149 menu.push :home, :home_path
150 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
150 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
151 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
151 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
152 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
152 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
153 menu.push :help, Redmine::Info.help_url, :last => true
153 menu.push :help, Redmine::Info.help_url, :last => true
154 end
154 end
155
155
156 Redmine::MenuManager.map :account_menu do |menu|
156 Redmine::MenuManager.map :account_menu do |menu|
157 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
157 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
158 menu.push :register, { :controller => 'account', :action => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
158 menu.push :register, { :controller => 'account', :action => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
159 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
159 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
160 menu.push :logout, :signout_path, :if => Proc.new { User.current.logged? }
160 menu.push :logout, :signout_path, :if => Proc.new { User.current.logged? }
161 end
161 end
162
162
163 Redmine::MenuManager.map :application_menu do |menu|
163 Redmine::MenuManager.map :application_menu do |menu|
164 # Empty
164 # Empty
165 end
165 end
166
166
167 Redmine::MenuManager.map :admin_menu do |menu|
167 Redmine::MenuManager.map :admin_menu do |menu|
168 menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
168 menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
169 menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
169 menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
170 menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
170 menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
171 menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
171 menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
172 menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
172 menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
173 menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
173 menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
174 :html => {:class => 'issue_statuses'}
174 :html => {:class => 'issue_statuses'}
175 menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
175 menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
176 menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
176 menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
177 :html => {:class => 'custom_fields'}
177 :html => {:class => 'custom_fields'}
178 menu.push :enumerations, {:controller => 'enumerations'}
178 menu.push :enumerations, {:controller => 'enumerations'}
179 menu.push :settings, {:controller => 'settings'}
179 menu.push :settings, {:controller => 'settings'}
180 menu.push :ldap_authentication, {:controller => 'ldap_auth_sources', :action => 'index'},
180 menu.push :ldap_authentication, {:controller => 'ldap_auth_sources', :action => 'index'},
181 :html => {:class => 'server_authentication'}
181 :html => {:class => 'server_authentication'}
182 menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
182 menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
183 menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
183 menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
184 end
184 end
185
185
186 Redmine::MenuManager.map :project_menu do |menu|
186 Redmine::MenuManager.map :project_menu do |menu|
187 menu.push :overview, { :controller => 'projects', :action => 'show' }
187 menu.push :overview, { :controller => 'projects', :action => 'show' }
188 menu.push :activity, { :controller => 'activities', :action => 'index' }
188 menu.push :activity, { :controller => 'activities', :action => 'index' }
189 menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id,
189 menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id,
190 :if => Proc.new { |p| p.shared_versions.any? }
190 :if => Proc.new { |p| p.shared_versions.any? }
191 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
191 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
192 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
192 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
193 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
193 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
194 menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
194 menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
195 menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
195 menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
196 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
196 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
197 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
197 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
198 menu.push :wiki, { :controller => 'wiki', :action => 'index', :page => nil },
198 menu.push :wiki, { :controller => 'wiki', :action => 'index', :page => nil }, :param => :project_id,
199 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
199 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
200 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
200 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
201 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
201 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
202 menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural, :param => :project_id
202 menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural, :param => :project_id
203 menu.push :repository, { :controller => 'repositories', :action => 'show' },
203 menu.push :repository, { :controller => 'repositories', :action => 'show' },
204 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
204 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
205 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
205 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
206 end
206 end
207
207
208 Redmine::Activity.map do |activity|
208 Redmine::Activity.map do |activity|
209 activity.register :issues, :class_name => %w(Issue Journal)
209 activity.register :issues, :class_name => %w(Issue Journal)
210 activity.register :changesets
210 activity.register :changesets
211 activity.register :news
211 activity.register :news
212 activity.register :documents, :class_name => %w(Document Attachment)
212 activity.register :documents, :class_name => %w(Document Attachment)
213 activity.register :files, :class_name => 'Attachment'
213 activity.register :files, :class_name => 'Attachment'
214 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
214 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
215 activity.register :messages, :default => false
215 activity.register :messages, :default => false
216 activity.register :time_entries, :default => false
216 activity.register :time_entries, :default => false
217 end
217 end
218
218
219 Redmine::Search.map do |search|
219 Redmine::Search.map do |search|
220 search.register :issues
220 search.register :issues
221 search.register :news
221 search.register :news
222 search.register :documents
222 search.register :documents
223 search.register :changesets
223 search.register :changesets
224 search.register :wiki_pages
224 search.register :wiki_pages
225 search.register :messages
225 search.register :messages
226 search.register :projects
226 search.register :projects
227 end
227 end
228
228
229 Redmine::WikiFormatting.map do |format|
229 Redmine::WikiFormatting.map do |format|
230 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
230 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
231 end
231 end
@@ -1,365 +1,365
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 require File.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'wiki_controller'
19 require 'wiki_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class WikiController; def rescue_action(e) raise e end; end
22 class WikiController; def rescue_action(e) raise e end; end
23
23
24 class WikiControllerTest < ActionController::TestCase
24 class WikiControllerTest < ActionController::TestCase
25 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions, :attachments
25 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions, :attachments
26
26
27 def setup
27 def setup
28 @controller = WikiController.new
28 @controller = WikiController.new
29 @request = ActionController::TestRequest.new
29 @request = ActionController::TestRequest.new
30 @response = ActionController::TestResponse.new
30 @response = ActionController::TestResponse.new
31 User.current = nil
31 User.current = nil
32 end
32 end
33
33
34 def test_show_start_page
34 def test_show_start_page
35 get :index, :id => 'ecookbook'
35 get :index, :project_id => 'ecookbook'
36 assert_response :success
36 assert_response :success
37 assert_template 'show'
37 assert_template 'show'
38 assert_tag :tag => 'h1', :content => /CookBook documentation/
38 assert_tag :tag => 'h1', :content => /CookBook documentation/
39
39
40 # child_pages macro
40 # child_pages macro
41 assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
41 assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
42 :child => { :tag => 'li',
42 :child => { :tag => 'li',
43 :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
43 :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
44 :content => 'Page with an inline image' } }
44 :content => 'Page with an inline image' } }
45 end
45 end
46
46
47 def test_show_page_with_name
47 def test_show_page_with_name
48 get :index, :id => 1, :page => 'Another_page'
48 get :index, :project_id => 1, :page => 'Another_page'
49 assert_response :success
49 assert_response :success
50 assert_template 'show'
50 assert_template 'show'
51 assert_tag :tag => 'h1', :content => /Another page/
51 assert_tag :tag => 'h1', :content => /Another page/
52 # Included page with an inline image
52 # Included page with an inline image
53 assert_tag :tag => 'p', :content => /This is an inline image/
53 assert_tag :tag => 'p', :content => /This is an inline image/
54 assert_tag :tag => 'img', :attributes => { :src => '/attachments/download/3',
54 assert_tag :tag => 'img', :attributes => { :src => '/attachments/download/3',
55 :alt => 'This is a logo' }
55 :alt => 'This is a logo' }
56 end
56 end
57
57
58 def test_show_with_sidebar
58 def test_show_with_sidebar
59 page = Project.find(1).wiki.pages.new(:title => 'Sidebar')
59 page = Project.find(1).wiki.pages.new(:title => 'Sidebar')
60 page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
60 page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
61 page.save!
61 page.save!
62
62
63 get :index, :id => 1, :page => 'Another_page'
63 get :index, :project_id => 1, :page => 'Another_page'
64 assert_response :success
64 assert_response :success
65 assert_tag :tag => 'div', :attributes => {:id => 'sidebar'},
65 assert_tag :tag => 'div', :attributes => {:id => 'sidebar'},
66 :content => /Side bar content for test_show_with_sidebar/
66 :content => /Side bar content for test_show_with_sidebar/
67 end
67 end
68
68
69 def test_show_unexistent_page_without_edit_right
69 def test_show_unexistent_page_without_edit_right
70 get :index, :id => 1, :page => 'Unexistent page'
70 get :index, :project_id => 1, :page => 'Unexistent page'
71 assert_response 404
71 assert_response 404
72 end
72 end
73
73
74 def test_show_unexistent_page_with_edit_right
74 def test_show_unexistent_page_with_edit_right
75 @request.session[:user_id] = 2
75 @request.session[:user_id] = 2
76 get :index, :id => 1, :page => 'Unexistent page'
76 get :index, :project_id => 1, :page => 'Unexistent page'
77 assert_response :success
77 assert_response :success
78 assert_template 'edit'
78 assert_template 'edit'
79 end
79 end
80
80
81 def test_create_page
81 def test_create_page
82 @request.session[:user_id] = 2
82 @request.session[:user_id] = 2
83 post :edit, :id => 1,
83 post :edit, :project_id => 1,
84 :page => 'New page',
84 :page => 'New page',
85 :content => {:comments => 'Created the page',
85 :content => {:comments => 'Created the page',
86 :text => "h1. New page\n\nThis is a new page",
86 :text => "h1. New page\n\nThis is a new page",
87 :version => 0}
87 :version => 0}
88 assert_redirected_to :action => 'index', :id => 'ecookbook', :page => 'New_page'
88 assert_redirected_to :action => 'index', :project_id => 'ecookbook', :page => 'New_page'
89 page = Project.find(1).wiki.find_page('New page')
89 page = Project.find(1).wiki.find_page('New page')
90 assert !page.new_record?
90 assert !page.new_record?
91 assert_not_nil page.content
91 assert_not_nil page.content
92 assert_equal 'Created the page', page.content.comments
92 assert_equal 'Created the page', page.content.comments
93 end
93 end
94
94
95 def test_create_page_with_attachments
95 def test_create_page_with_attachments
96 @request.session[:user_id] = 2
96 @request.session[:user_id] = 2
97 assert_difference 'WikiPage.count' do
97 assert_difference 'WikiPage.count' do
98 assert_difference 'Attachment.count' do
98 assert_difference 'Attachment.count' do
99 post :edit, :id => 1,
99 post :edit, :project_id => 1,
100 :page => 'New page',
100 :page => 'New page',
101 :content => {:comments => 'Created the page',
101 :content => {:comments => 'Created the page',
102 :text => "h1. New page\n\nThis is a new page",
102 :text => "h1. New page\n\nThis is a new page",
103 :version => 0},
103 :version => 0},
104 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
104 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
105 end
105 end
106 end
106 end
107 page = Project.find(1).wiki.find_page('New page')
107 page = Project.find(1).wiki.find_page('New page')
108 assert_equal 1, page.attachments.count
108 assert_equal 1, page.attachments.count
109 assert_equal 'testfile.txt', page.attachments.first.filename
109 assert_equal 'testfile.txt', page.attachments.first.filename
110 end
110 end
111
111
112 def test_preview
112 def test_preview
113 @request.session[:user_id] = 2
113 @request.session[:user_id] = 2
114 xhr :post, :preview, :id => 1, :page => 'CookBook_documentation',
114 xhr :post, :preview, :project_id => 1, :page => 'CookBook_documentation',
115 :content => { :comments => '',
115 :content => { :comments => '',
116 :text => 'this is a *previewed text*',
116 :text => 'this is a *previewed text*',
117 :version => 3 }
117 :version => 3 }
118 assert_response :success
118 assert_response :success
119 assert_template 'common/_preview'
119 assert_template 'common/_preview'
120 assert_tag :tag => 'strong', :content => /previewed text/
120 assert_tag :tag => 'strong', :content => /previewed text/
121 end
121 end
122
122
123 def test_preview_new_page
123 def test_preview_new_page
124 @request.session[:user_id] = 2
124 @request.session[:user_id] = 2
125 xhr :post, :preview, :id => 1, :page => 'New page',
125 xhr :post, :preview, :project_id => 1, :page => 'New page',
126 :content => { :text => 'h1. New page',
126 :content => { :text => 'h1. New page',
127 :comments => '',
127 :comments => '',
128 :version => 0 }
128 :version => 0 }
129 assert_response :success
129 assert_response :success
130 assert_template 'common/_preview'
130 assert_template 'common/_preview'
131 assert_tag :tag => 'h1', :content => /New page/
131 assert_tag :tag => 'h1', :content => /New page/
132 end
132 end
133
133
134 def test_history
134 def test_history
135 get :history, :id => 1, :page => 'CookBook_documentation'
135 get :history, :project_id => 1, :page => 'CookBook_documentation'
136 assert_response :success
136 assert_response :success
137 assert_template 'history'
137 assert_template 'history'
138 assert_not_nil assigns(:versions)
138 assert_not_nil assigns(:versions)
139 assert_equal 3, assigns(:versions).size
139 assert_equal 3, assigns(:versions).size
140 assert_select "input[type=submit][name=commit]"
140 assert_select "input[type=submit][name=commit]"
141 end
141 end
142
142
143 def test_history_with_one_version
143 def test_history_with_one_version
144 get :history, :id => 1, :page => 'Another_page'
144 get :history, :project_id => 1, :page => 'Another_page'
145 assert_response :success
145 assert_response :success
146 assert_template 'history'
146 assert_template 'history'
147 assert_not_nil assigns(:versions)
147 assert_not_nil assigns(:versions)
148 assert_equal 1, assigns(:versions).size
148 assert_equal 1, assigns(:versions).size
149 assert_select "input[type=submit][name=commit]", false
149 assert_select "input[type=submit][name=commit]", false
150 end
150 end
151
151
152 def test_diff
152 def test_diff
153 get :diff, :id => 1, :page => 'CookBook_documentation', :version => 2, :version_from => 1
153 get :diff, :project_id => 1, :page => 'CookBook_documentation', :version => 2, :version_from => 1
154 assert_response :success
154 assert_response :success
155 assert_template 'diff'
155 assert_template 'diff'
156 assert_tag :tag => 'span', :attributes => { :class => 'diff_in'},
156 assert_tag :tag => 'span', :attributes => { :class => 'diff_in'},
157 :content => /updated/
157 :content => /updated/
158 end
158 end
159
159
160 def test_annotate
160 def test_annotate
161 get :annotate, :id => 1, :page => 'CookBook_documentation', :version => 2
161 get :annotate, :project_id => 1, :page => 'CookBook_documentation', :version => 2
162 assert_response :success
162 assert_response :success
163 assert_template 'annotate'
163 assert_template 'annotate'
164 # Line 1
164 # Line 1
165 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '1' },
165 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '1' },
166 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /John Smith/ },
166 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /John Smith/ },
167 :child => { :tag => 'td', :content => /h1\. CookBook documentation/ }
167 :child => { :tag => 'td', :content => /h1\. CookBook documentation/ }
168 # Line 2
168 # Line 2
169 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '2' },
169 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '2' },
170 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /redMine Admin/ },
170 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /redMine Admin/ },
171 :child => { :tag => 'td', :content => /Some updated \[\[documentation\]\] here/ }
171 :child => { :tag => 'td', :content => /Some updated \[\[documentation\]\] here/ }
172 end
172 end
173
173
174 def test_rename_with_redirect
174 def test_rename_with_redirect
175 @request.session[:user_id] = 2
175 @request.session[:user_id] = 2
176 post :rename, :id => 1, :page => 'Another_page',
176 post :rename, :project_id => 1, :page => 'Another_page',
177 :wiki_page => { :title => 'Another renamed page',
177 :wiki_page => { :title => 'Another renamed page',
178 :redirect_existing_links => 1 }
178 :redirect_existing_links => 1 }
179 assert_redirected_to :action => 'index', :id => 'ecookbook', :page => 'Another_renamed_page'
179 assert_redirected_to :action => 'index', :project_id => 'ecookbook', :page => 'Another_renamed_page'
180 wiki = Project.find(1).wiki
180 wiki = Project.find(1).wiki
181 # Check redirects
181 # Check redirects
182 assert_not_nil wiki.find_page('Another page')
182 assert_not_nil wiki.find_page('Another page')
183 assert_nil wiki.find_page('Another page', :with_redirect => false)
183 assert_nil wiki.find_page('Another page', :with_redirect => false)
184 end
184 end
185
185
186 def test_rename_without_redirect
186 def test_rename_without_redirect
187 @request.session[:user_id] = 2
187 @request.session[:user_id] = 2
188 post :rename, :id => 1, :page => 'Another_page',
188 post :rename, :project_id => 1, :page => 'Another_page',
189 :wiki_page => { :title => 'Another renamed page',
189 :wiki_page => { :title => 'Another renamed page',
190 :redirect_existing_links => "0" }
190 :redirect_existing_links => "0" }
191 assert_redirected_to :action => 'index', :id => 'ecookbook', :page => 'Another_renamed_page'
191 assert_redirected_to :action => 'index', :project_id => 'ecookbook', :page => 'Another_renamed_page'
192 wiki = Project.find(1).wiki
192 wiki = Project.find(1).wiki
193 # Check that there's no redirects
193 # Check that there's no redirects
194 assert_nil wiki.find_page('Another page')
194 assert_nil wiki.find_page('Another page')
195 end
195 end
196
196
197 def test_destroy_child
197 def test_destroy_child
198 @request.session[:user_id] = 2
198 @request.session[:user_id] = 2
199 post :destroy, :id => 1, :page => 'Child_1'
199 post :destroy, :project_id => 1, :page => 'Child_1'
200 assert_redirected_to :action => 'page_index', :id => 'ecookbook'
200 assert_redirected_to :action => 'page_index', :project_id => 'ecookbook'
201 end
201 end
202
202
203 def test_destroy_parent
203 def test_destroy_parent
204 @request.session[:user_id] = 2
204 @request.session[:user_id] = 2
205 assert_no_difference('WikiPage.count') do
205 assert_no_difference('WikiPage.count') do
206 post :destroy, :id => 1, :page => 'Another_page'
206 post :destroy, :project_id => 1, :page => 'Another_page'
207 end
207 end
208 assert_response :success
208 assert_response :success
209 assert_template 'destroy'
209 assert_template 'destroy'
210 end
210 end
211
211
212 def test_destroy_parent_with_nullify
212 def test_destroy_parent_with_nullify
213 @request.session[:user_id] = 2
213 @request.session[:user_id] = 2
214 assert_difference('WikiPage.count', -1) do
214 assert_difference('WikiPage.count', -1) do
215 post :destroy, :id => 1, :page => 'Another_page', :todo => 'nullify'
215 post :destroy, :project_id => 1, :page => 'Another_page', :todo => 'nullify'
216 end
216 end
217 assert_redirected_to :action => 'page_index', :id => 'ecookbook'
217 assert_redirected_to :action => 'page_index', :project_id => 'ecookbook'
218 assert_nil WikiPage.find_by_id(2)
218 assert_nil WikiPage.find_by_id(2)
219 end
219 end
220
220
221 def test_destroy_parent_with_cascade
221 def test_destroy_parent_with_cascade
222 @request.session[:user_id] = 2
222 @request.session[:user_id] = 2
223 assert_difference('WikiPage.count', -3) do
223 assert_difference('WikiPage.count', -3) do
224 post :destroy, :id => 1, :page => 'Another_page', :todo => 'destroy'
224 post :destroy, :project_id => 1, :page => 'Another_page', :todo => 'destroy'
225 end
225 end
226 assert_redirected_to :action => 'page_index', :id => 'ecookbook'
226 assert_redirected_to :action => 'page_index', :project_id => 'ecookbook'
227 assert_nil WikiPage.find_by_id(2)
227 assert_nil WikiPage.find_by_id(2)
228 assert_nil WikiPage.find_by_id(5)
228 assert_nil WikiPage.find_by_id(5)
229 end
229 end
230
230
231 def test_destroy_parent_with_reassign
231 def test_destroy_parent_with_reassign
232 @request.session[:user_id] = 2
232 @request.session[:user_id] = 2
233 assert_difference('WikiPage.count', -1) do
233 assert_difference('WikiPage.count', -1) do
234 post :destroy, :id => 1, :page => 'Another_page', :todo => 'reassign', :reassign_to_id => 1
234 post :destroy, :project_id => 1, :page => 'Another_page', :todo => 'reassign', :reassign_to_id => 1
235 end
235 end
236 assert_redirected_to :action => 'page_index', :id => 'ecookbook'
236 assert_redirected_to :action => 'page_index', :project_id => 'ecookbook'
237 assert_nil WikiPage.find_by_id(2)
237 assert_nil WikiPage.find_by_id(2)
238 assert_equal WikiPage.find(1), WikiPage.find_by_id(5).parent
238 assert_equal WikiPage.find(1), WikiPage.find_by_id(5).parent
239 end
239 end
240
240
241 def test_page_index
241 def test_page_index
242 get :page_index, :id => 'ecookbook'
242 get :page_index, :project_id => 'ecookbook'
243 assert_response :success
243 assert_response :success
244 assert_template 'page_index'
244 assert_template 'page_index'
245 pages = assigns(:pages)
245 pages = assigns(:pages)
246 assert_not_nil pages
246 assert_not_nil pages
247 assert_equal Project.find(1).wiki.pages.size, pages.size
247 assert_equal Project.find(1).wiki.pages.size, pages.size
248
248
249 assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
249 assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
250 :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/CookBook_documentation' },
250 :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/CookBook_documentation' },
251 :content => 'CookBook documentation' },
251 :content => 'CookBook documentation' },
252 :child => { :tag => 'ul',
252 :child => { :tag => 'ul',
253 :child => { :tag => 'li',
253 :child => { :tag => 'li',
254 :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
254 :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
255 :content => 'Page with an inline image' } } } },
255 :content => 'Page with an inline image' } } } },
256 :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Another_page' },
256 :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Another_page' },
257 :content => 'Another page' } }
257 :content => 'Another page' } }
258 end
258 end
259
259
260 context "GET :export" do
260 context "GET :export" do
261 context "with an authorized user to export the wiki" do
261 context "with an authorized user to export the wiki" do
262 setup do
262 setup do
263 @request.session[:user_id] = 2
263 @request.session[:user_id] = 2
264 get :export, :id => 'ecookbook'
264 get :export, :project_id => 'ecookbook'
265 end
265 end
266
266
267 should_respond_with :success
267 should_respond_with :success
268 should_assign_to :pages
268 should_assign_to :pages
269 should_respond_with_content_type "text/html"
269 should_respond_with_content_type "text/html"
270 should "export all of the wiki pages to a single html file" do
270 should "export all of the wiki pages to a single html file" do
271 assert_select "a[name=?]", "CookBook_documentation"
271 assert_select "a[name=?]", "CookBook_documentation"
272 assert_select "a[name=?]", "Another_page"
272 assert_select "a[name=?]", "Another_page"
273 assert_select "a[name=?]", "Page_with_an_inline_image"
273 assert_select "a[name=?]", "Page_with_an_inline_image"
274 end
274 end
275
275
276 end
276 end
277
277
278 context "with an unauthorized user" do
278 context "with an unauthorized user" do
279 setup do
279 setup do
280 get :export, :id => 'ecookbook'
280 get :export, :project_id => 'ecookbook'
281
281
282 should_respond_with :redirect
282 should_respond_with :redirect
283 should_redirect_to('wiki index') { {:action => 'index', :id => @project, :page => nil} }
283 should_redirect_to('wiki index') { {:action => 'index', :project_id => @project, :page => nil} }
284 end
284 end
285 end
285 end
286 end
286 end
287
287
288 context "GET :date_index" do
288 context "GET :date_index" do
289 setup do
289 setup do
290 get :date_index, :id => 'ecookbook'
290 get :date_index, :project_id => 'ecookbook'
291 end
291 end
292
292
293 should_respond_with :success
293 should_respond_with :success
294 should_assign_to :pages
294 should_assign_to :pages
295 should_assign_to :pages_by_date
295 should_assign_to :pages_by_date
296 should_render_template 'wiki/date_index'
296 should_render_template 'wiki/date_index'
297
297
298 end
298 end
299
299
300 def test_not_found
300 def test_not_found
301 get :index, :id => 999
301 get :index, :project_id => 999
302 assert_response 404
302 assert_response 404
303 end
303 end
304
304
305 def test_protect_page
305 def test_protect_page
306 page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page')
306 page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page')
307 assert !page.protected?
307 assert !page.protected?
308 @request.session[:user_id] = 2
308 @request.session[:user_id] = 2
309 post :protect, :id => 1, :page => page.title, :protected => '1'
309 post :protect, :project_id => 1, :page => page.title, :protected => '1'
310 assert_redirected_to :action => 'index', :id => 'ecookbook', :page => 'Another_page'
310 assert_redirected_to :action => 'index', :project_id => 'ecookbook', :page => 'Another_page'
311 assert page.reload.protected?
311 assert page.reload.protected?
312 end
312 end
313
313
314 def test_unprotect_page
314 def test_unprotect_page
315 page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation')
315 page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation')
316 assert page.protected?
316 assert page.protected?
317 @request.session[:user_id] = 2
317 @request.session[:user_id] = 2
318 post :protect, :id => 1, :page => page.title, :protected => '0'
318 post :protect, :project_id => 1, :page => page.title, :protected => '0'
319 assert_redirected_to :action => 'index', :id => 'ecookbook', :page => 'CookBook_documentation'
319 assert_redirected_to :action => 'index', :project_id => 'ecookbook', :page => 'CookBook_documentation'
320 assert !page.reload.protected?
320 assert !page.reload.protected?
321 end
321 end
322
322
323 def test_show_page_with_edit_link
323 def test_show_page_with_edit_link
324 @request.session[:user_id] = 2
324 @request.session[:user_id] = 2
325 get :index, :id => 1
325 get :index, :project_id => 1
326 assert_response :success
326 assert_response :success
327 assert_template 'show'
327 assert_template 'show'
328 assert_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
328 assert_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
329 end
329 end
330
330
331 def test_show_page_without_edit_link
331 def test_show_page_without_edit_link
332 @request.session[:user_id] = 4
332 @request.session[:user_id] = 4
333 get :index, :id => 1
333 get :index, :project_id => 1
334 assert_response :success
334 assert_response :success
335 assert_template 'show'
335 assert_template 'show'
336 assert_no_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
336 assert_no_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
337 end
337 end
338
338
339 def test_edit_unprotected_page
339 def test_edit_unprotected_page
340 # Non members can edit unprotected wiki pages
340 # Non members can edit unprotected wiki pages
341 @request.session[:user_id] = 4
341 @request.session[:user_id] = 4
342 get :edit, :id => 1, :page => 'Another_page'
342 get :edit, :project_id => 1, :page => 'Another_page'
343 assert_response :success
343 assert_response :success
344 assert_template 'edit'
344 assert_template 'edit'
345 end
345 end
346
346
347 def test_edit_protected_page_by_nonmember
347 def test_edit_protected_page_by_nonmember
348 # Non members can't edit protected wiki pages
348 # Non members can't edit protected wiki pages
349 @request.session[:user_id] = 4
349 @request.session[:user_id] = 4
350 get :edit, :id => 1, :page => 'CookBook_documentation'
350 get :edit, :project_id => 1, :page => 'CookBook_documentation'
351 assert_response 403
351 assert_response 403
352 end
352 end
353
353
354 def test_edit_protected_page_by_member
354 def test_edit_protected_page_by_member
355 @request.session[:user_id] = 2
355 @request.session[:user_id] = 2
356 get :edit, :id => 1, :page => 'CookBook_documentation'
356 get :edit, :project_id => 1, :page => 'CookBook_documentation'
357 assert_response :success
357 assert_response :success
358 assert_template 'edit'
358 assert_template 'edit'
359 end
359 end
360
360
361 def test_history_of_non_existing_page_should_return_404
361 def test_history_of_non_existing_page_should_return_404
362 get :history, :id => 1, :page => 'Unknown_page'
362 get :history, :project_id => 1, :page => 'Unknown_page'
363 assert_response 404
363 assert_response 404
364 end
364 end
365 end
365 end
@@ -1,342 +1,342
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
2 # Copyright (C) 2006-2010 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 require "#{File.dirname(__FILE__)}/../test_helper"
18 require "#{File.dirname(__FILE__)}/../test_helper"
19
19
20 class RoutingTest < ActionController::IntegrationTest
20 class RoutingTest < ActionController::IntegrationTest
21 context "activities" do
21 context "activities" do
22 should_route :get, "/activity", :controller => 'activities', :action => 'index', :id => nil
22 should_route :get, "/activity", :controller => 'activities', :action => 'index', :id => nil
23 should_route :get, "/activity.atom", :controller => 'activities', :action => 'index', :id => nil, :format => 'atom'
23 should_route :get, "/activity.atom", :controller => 'activities', :action => 'index', :id => nil, :format => 'atom'
24 end
24 end
25
25
26 context "attachments" do
26 context "attachments" do
27 should_route :get, "/attachments/1", :controller => 'attachments', :action => 'show', :id => '1'
27 should_route :get, "/attachments/1", :controller => 'attachments', :action => 'show', :id => '1'
28 should_route :get, "/attachments/1/filename.ext", :controller => 'attachments', :action => 'show', :id => '1', :filename => 'filename.ext'
28 should_route :get, "/attachments/1/filename.ext", :controller => 'attachments', :action => 'show', :id => '1', :filename => 'filename.ext'
29 should_route :get, "/attachments/download/1", :controller => 'attachments', :action => 'download', :id => '1'
29 should_route :get, "/attachments/download/1", :controller => 'attachments', :action => 'download', :id => '1'
30 should_route :get, "/attachments/download/1/filename.ext", :controller => 'attachments', :action => 'download', :id => '1', :filename => 'filename.ext'
30 should_route :get, "/attachments/download/1/filename.ext", :controller => 'attachments', :action => 'download', :id => '1', :filename => 'filename.ext'
31 end
31 end
32
32
33 context "boards" do
33 context "boards" do
34 should_route :get, "/projects/world_domination/boards", :controller => 'boards', :action => 'index', :project_id => 'world_domination'
34 should_route :get, "/projects/world_domination/boards", :controller => 'boards', :action => 'index', :project_id => 'world_domination'
35 should_route :get, "/projects/world_domination/boards/new", :controller => 'boards', :action => 'new', :project_id => 'world_domination'
35 should_route :get, "/projects/world_domination/boards/new", :controller => 'boards', :action => 'new', :project_id => 'world_domination'
36 should_route :get, "/projects/world_domination/boards/44", :controller => 'boards', :action => 'show', :project_id => 'world_domination', :id => '44'
36 should_route :get, "/projects/world_domination/boards/44", :controller => 'boards', :action => 'show', :project_id => 'world_domination', :id => '44'
37 should_route :get, "/projects/world_domination/boards/44.atom", :controller => 'boards', :action => 'show', :project_id => 'world_domination', :id => '44', :format => 'atom'
37 should_route :get, "/projects/world_domination/boards/44.atom", :controller => 'boards', :action => 'show', :project_id => 'world_domination', :id => '44', :format => 'atom'
38 should_route :get, "/projects/world_domination/boards/44/edit", :controller => 'boards', :action => 'edit', :project_id => 'world_domination', :id => '44'
38 should_route :get, "/projects/world_domination/boards/44/edit", :controller => 'boards', :action => 'edit', :project_id => 'world_domination', :id => '44'
39
39
40 should_route :post, "/projects/world_domination/boards/new", :controller => 'boards', :action => 'new', :project_id => 'world_domination'
40 should_route :post, "/projects/world_domination/boards/new", :controller => 'boards', :action => 'new', :project_id => 'world_domination'
41 should_route :post, "/projects/world_domination/boards/44/edit", :controller => 'boards', :action => 'edit', :project_id => 'world_domination', :id => '44'
41 should_route :post, "/projects/world_domination/boards/44/edit", :controller => 'boards', :action => 'edit', :project_id => 'world_domination', :id => '44'
42 should_route :post, "/projects/world_domination/boards/44/destroy", :controller => 'boards', :action => 'destroy', :project_id => 'world_domination', :id => '44'
42 should_route :post, "/projects/world_domination/boards/44/destroy", :controller => 'boards', :action => 'destroy', :project_id => 'world_domination', :id => '44'
43
43
44 end
44 end
45
45
46 context "documents" do
46 context "documents" do
47 should_route :get, "/projects/567/documents", :controller => 'documents', :action => 'index', :project_id => '567'
47 should_route :get, "/projects/567/documents", :controller => 'documents', :action => 'index', :project_id => '567'
48 should_route :get, "/projects/567/documents/new", :controller => 'documents', :action => 'new', :project_id => '567'
48 should_route :get, "/projects/567/documents/new", :controller => 'documents', :action => 'new', :project_id => '567'
49 should_route :get, "/documents/22", :controller => 'documents', :action => 'show', :id => '22'
49 should_route :get, "/documents/22", :controller => 'documents', :action => 'show', :id => '22'
50 should_route :get, "/documents/22/edit", :controller => 'documents', :action => 'edit', :id => '22'
50 should_route :get, "/documents/22/edit", :controller => 'documents', :action => 'edit', :id => '22'
51
51
52 should_route :post, "/projects/567/documents/new", :controller => 'documents', :action => 'new', :project_id => '567'
52 should_route :post, "/projects/567/documents/new", :controller => 'documents', :action => 'new', :project_id => '567'
53 should_route :post, "/documents/567/edit", :controller => 'documents', :action => 'edit', :id => '567'
53 should_route :post, "/documents/567/edit", :controller => 'documents', :action => 'edit', :id => '567'
54 should_route :post, "/documents/567/destroy", :controller => 'documents', :action => 'destroy', :id => '567'
54 should_route :post, "/documents/567/destroy", :controller => 'documents', :action => 'destroy', :id => '567'
55 end
55 end
56
56
57 context "issues" do
57 context "issues" do
58 # REST actions
58 # REST actions
59 should_route :get, "/issues", :controller => 'issues', :action => 'index'
59 should_route :get, "/issues", :controller => 'issues', :action => 'index'
60 should_route :get, "/issues.pdf", :controller => 'issues', :action => 'index', :format => 'pdf'
60 should_route :get, "/issues.pdf", :controller => 'issues', :action => 'index', :format => 'pdf'
61 should_route :get, "/issues.atom", :controller => 'issues', :action => 'index', :format => 'atom'
61 should_route :get, "/issues.atom", :controller => 'issues', :action => 'index', :format => 'atom'
62 should_route :get, "/issues.xml", :controller => 'issues', :action => 'index', :format => 'xml'
62 should_route :get, "/issues.xml", :controller => 'issues', :action => 'index', :format => 'xml'
63 should_route :get, "/projects/23/issues", :controller => 'issues', :action => 'index', :project_id => '23'
63 should_route :get, "/projects/23/issues", :controller => 'issues', :action => 'index', :project_id => '23'
64 should_route :get, "/projects/23/issues.pdf", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'pdf'
64 should_route :get, "/projects/23/issues.pdf", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'pdf'
65 should_route :get, "/projects/23/issues.atom", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'atom'
65 should_route :get, "/projects/23/issues.atom", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'atom'
66 should_route :get, "/projects/23/issues.xml", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'xml'
66 should_route :get, "/projects/23/issues.xml", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'xml'
67 should_route :get, "/issues/64", :controller => 'issues', :action => 'show', :id => '64'
67 should_route :get, "/issues/64", :controller => 'issues', :action => 'show', :id => '64'
68 should_route :get, "/issues/64.pdf", :controller => 'issues', :action => 'show', :id => '64', :format => 'pdf'
68 should_route :get, "/issues/64.pdf", :controller => 'issues', :action => 'show', :id => '64', :format => 'pdf'
69 should_route :get, "/issues/64.atom", :controller => 'issues', :action => 'show', :id => '64', :format => 'atom'
69 should_route :get, "/issues/64.atom", :controller => 'issues', :action => 'show', :id => '64', :format => 'atom'
70 should_route :get, "/issues/64.xml", :controller => 'issues', :action => 'show', :id => '64', :format => 'xml'
70 should_route :get, "/issues/64.xml", :controller => 'issues', :action => 'show', :id => '64', :format => 'xml'
71
71
72 should_route :get, "/projects/23/issues/new", :controller => 'issues', :action => 'new', :project_id => '23'
72 should_route :get, "/projects/23/issues/new", :controller => 'issues', :action => 'new', :project_id => '23'
73 should_route :post, "/projects/23/issues", :controller => 'issues', :action => 'create', :project_id => '23'
73 should_route :post, "/projects/23/issues", :controller => 'issues', :action => 'create', :project_id => '23'
74 should_route :post, "/issues.xml", :controller => 'issues', :action => 'create', :format => 'xml'
74 should_route :post, "/issues.xml", :controller => 'issues', :action => 'create', :format => 'xml'
75
75
76 should_route :get, "/issues/64/edit", :controller => 'issues', :action => 'edit', :id => '64'
76 should_route :get, "/issues/64/edit", :controller => 'issues', :action => 'edit', :id => '64'
77 # TODO: Should use PUT
77 # TODO: Should use PUT
78 should_route :post, "/issues/64/edit", :controller => 'issues', :action => 'edit', :id => '64'
78 should_route :post, "/issues/64/edit", :controller => 'issues', :action => 'edit', :id => '64'
79 should_route :put, "/issues/1.xml", :controller => 'issues', :action => 'update', :id => '1', :format => 'xml'
79 should_route :put, "/issues/1.xml", :controller => 'issues', :action => 'update', :id => '1', :format => 'xml'
80
80
81 # TODO: Should use DELETE
81 # TODO: Should use DELETE
82 should_route :post, "/issues/64/destroy", :controller => 'issues', :action => 'destroy', :id => '64'
82 should_route :post, "/issues/64/destroy", :controller => 'issues', :action => 'destroy', :id => '64'
83 should_route :delete, "/issues/1.xml", :controller => 'issues', :action => 'destroy', :id => '1', :format => 'xml'
83 should_route :delete, "/issues/1.xml", :controller => 'issues', :action => 'destroy', :id => '1', :format => 'xml'
84
84
85 # Extra actions
85 # Extra actions
86 should_route :get, "/projects/23/issues/64/copy", :controller => 'issues', :action => 'new', :project_id => '23', :copy_from => '64'
86 should_route :get, "/projects/23/issues/64/copy", :controller => 'issues', :action => 'new', :project_id => '23', :copy_from => '64'
87
87
88 should_route :get, "/issues/move/new", :controller => 'issue_moves', :action => 'new'
88 should_route :get, "/issues/move/new", :controller => 'issue_moves', :action => 'new'
89 should_route :post, "/issues/move", :controller => 'issue_moves', :action => 'create'
89 should_route :post, "/issues/move", :controller => 'issue_moves', :action => 'create'
90
90
91 should_route :post, "/issues/1/quoted", :controller => 'journals', :action => 'new', :id => '1'
91 should_route :post, "/issues/1/quoted", :controller => 'journals', :action => 'new', :id => '1'
92
92
93 should_route :get, "/issues/calendar", :controller => 'calendars', :action => 'show'
93 should_route :get, "/issues/calendar", :controller => 'calendars', :action => 'show'
94 should_route :put, "/issues/calendar", :controller => 'calendars', :action => 'update'
94 should_route :put, "/issues/calendar", :controller => 'calendars', :action => 'update'
95 should_route :get, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'show', :project_id => 'project-name'
95 should_route :get, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'show', :project_id => 'project-name'
96 should_route :put, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'update', :project_id => 'project-name'
96 should_route :put, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'update', :project_id => 'project-name'
97
97
98 should_route :get, "/issues/gantt", :controller => 'gantts', :action => 'show'
98 should_route :get, "/issues/gantt", :controller => 'gantts', :action => 'show'
99 should_route :put, "/issues/gantt", :controller => 'gantts', :action => 'update'
99 should_route :put, "/issues/gantt", :controller => 'gantts', :action => 'update'
100 should_route :get, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'show', :project_id => 'project-name'
100 should_route :get, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'show', :project_id => 'project-name'
101 should_route :put, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'update', :project_id => 'project-name'
101 should_route :put, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'update', :project_id => 'project-name'
102
102
103 should_route :get, "/issues/auto_complete", :controller => 'auto_completes', :action => 'issues'
103 should_route :get, "/issues/auto_complete", :controller => 'auto_completes', :action => 'issues'
104
104
105 should_route :get, "/issues/preview/123", :controller => 'previews', :action => 'issue', :id => '123'
105 should_route :get, "/issues/preview/123", :controller => 'previews', :action => 'issue', :id => '123'
106 should_route :post, "/issues/preview/123", :controller => 'previews', :action => 'issue', :id => '123'
106 should_route :post, "/issues/preview/123", :controller => 'previews', :action => 'issue', :id => '123'
107 should_route :get, "/issues/context_menu", :controller => 'context_menus', :action => 'issues'
107 should_route :get, "/issues/context_menu", :controller => 'context_menus', :action => 'issues'
108 should_route :post, "/issues/context_menu", :controller => 'context_menus', :action => 'issues'
108 should_route :post, "/issues/context_menu", :controller => 'context_menus', :action => 'issues'
109
109
110 should_route :get, "/issues/changes", :controller => 'journals', :action => 'index'
110 should_route :get, "/issues/changes", :controller => 'journals', :action => 'index'
111
111
112 should_route :get, "/issues/bulk_edit", :controller => 'issues', :action => 'bulk_edit'
112 should_route :get, "/issues/bulk_edit", :controller => 'issues', :action => 'bulk_edit'
113 should_route :post, "/issues/bulk_edit", :controller => 'issues', :action => 'bulk_update'
113 should_route :post, "/issues/bulk_edit", :controller => 'issues', :action => 'bulk_update'
114 end
114 end
115
115
116 context "issue categories" do
116 context "issue categories" do
117 should_route :get, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
117 should_route :get, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
118
118
119 should_route :post, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
119 should_route :post, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
120 end
120 end
121
121
122 context "issue relations" do
122 context "issue relations" do
123 should_route :post, "/issues/1/relations", :controller => 'issue_relations', :action => 'new', :issue_id => '1'
123 should_route :post, "/issues/1/relations", :controller => 'issue_relations', :action => 'new', :issue_id => '1'
124 should_route :post, "/issues/1/relations/23/destroy", :controller => 'issue_relations', :action => 'destroy', :issue_id => '1', :id => '23'
124 should_route :post, "/issues/1/relations/23/destroy", :controller => 'issue_relations', :action => 'destroy', :issue_id => '1', :id => '23'
125 end
125 end
126
126
127 context "issue reports" do
127 context "issue reports" do
128 should_route :get, "/projects/567/issues/report", :controller => 'reports', :action => 'issue_report', :id => '567'
128 should_route :get, "/projects/567/issues/report", :controller => 'reports', :action => 'issue_report', :id => '567'
129 should_route :get, "/projects/567/issues/report/assigned_to", :controller => 'reports', :action => 'issue_report_details', :id => '567', :detail => 'assigned_to'
129 should_route :get, "/projects/567/issues/report/assigned_to", :controller => 'reports', :action => 'issue_report_details', :id => '567', :detail => 'assigned_to'
130 end
130 end
131
131
132 context "members" do
132 context "members" do
133 should_route :post, "/projects/5234/members/new", :controller => 'members', :action => 'new', :id => '5234'
133 should_route :post, "/projects/5234/members/new", :controller => 'members', :action => 'new', :id => '5234'
134 end
134 end
135
135
136 context "messages" do
136 context "messages" do
137 should_route :get, "/boards/22/topics/2", :controller => 'messages', :action => 'show', :id => '2', :board_id => '22'
137 should_route :get, "/boards/22/topics/2", :controller => 'messages', :action => 'show', :id => '2', :board_id => '22'
138 should_route :get, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
138 should_route :get, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
139 should_route :get, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
139 should_route :get, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
140
140
141 should_route :post, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
141 should_route :post, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
142 should_route :post, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
142 should_route :post, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
143 should_route :post, "/boards/22/topics/555/replies", :controller => 'messages', :action => 'reply', :id => '555', :board_id => '22'
143 should_route :post, "/boards/22/topics/555/replies", :controller => 'messages', :action => 'reply', :id => '555', :board_id => '22'
144 should_route :post, "/boards/22/topics/555/destroy", :controller => 'messages', :action => 'destroy', :id => '555', :board_id => '22'
144 should_route :post, "/boards/22/topics/555/destroy", :controller => 'messages', :action => 'destroy', :id => '555', :board_id => '22'
145 end
145 end
146
146
147 context "news" do
147 context "news" do
148 should_route :get, "/news", :controller => 'news', :action => 'index'
148 should_route :get, "/news", :controller => 'news', :action => 'index'
149 should_route :get, "/news.atom", :controller => 'news', :action => 'index', :format => 'atom'
149 should_route :get, "/news.atom", :controller => 'news', :action => 'index', :format => 'atom'
150 should_route :get, "/news.xml", :controller => 'news', :action => 'index', :format => 'xml'
150 should_route :get, "/news.xml", :controller => 'news', :action => 'index', :format => 'xml'
151 should_route :get, "/news.json", :controller => 'news', :action => 'index', :format => 'json'
151 should_route :get, "/news.json", :controller => 'news', :action => 'index', :format => 'json'
152 should_route :get, "/projects/567/news", :controller => 'news', :action => 'index', :project_id => '567'
152 should_route :get, "/projects/567/news", :controller => 'news', :action => 'index', :project_id => '567'
153 should_route :get, "/projects/567/news.atom", :controller => 'news', :action => 'index', :format => 'atom', :project_id => '567'
153 should_route :get, "/projects/567/news.atom", :controller => 'news', :action => 'index', :format => 'atom', :project_id => '567'
154 should_route :get, "/projects/567/news.xml", :controller => 'news', :action => 'index', :format => 'xml', :project_id => '567'
154 should_route :get, "/projects/567/news.xml", :controller => 'news', :action => 'index', :format => 'xml', :project_id => '567'
155 should_route :get, "/projects/567/news.json", :controller => 'news', :action => 'index', :format => 'json', :project_id => '567'
155 should_route :get, "/projects/567/news.json", :controller => 'news', :action => 'index', :format => 'json', :project_id => '567'
156 should_route :get, "/news/2", :controller => 'news', :action => 'show', :id => '2'
156 should_route :get, "/news/2", :controller => 'news', :action => 'show', :id => '2'
157 should_route :get, "/projects/567/news/new", :controller => 'news', :action => 'new', :project_id => '567'
157 should_route :get, "/projects/567/news/new", :controller => 'news', :action => 'new', :project_id => '567'
158 should_route :get, "/news/234", :controller => 'news', :action => 'show', :id => '234'
158 should_route :get, "/news/234", :controller => 'news', :action => 'show', :id => '234'
159 should_route :get, "/news/567/edit", :controller => 'news', :action => 'edit', :id => '567'
159 should_route :get, "/news/567/edit", :controller => 'news', :action => 'edit', :id => '567'
160 should_route :get, "/news/preview", :controller => 'previews', :action => 'news'
160 should_route :get, "/news/preview", :controller => 'previews', :action => 'news'
161
161
162 should_route :post, "/projects/567/news", :controller => 'news', :action => 'create', :project_id => '567'
162 should_route :post, "/projects/567/news", :controller => 'news', :action => 'create', :project_id => '567'
163 should_route :post, "/news/567/comments", :controller => 'comments', :action => 'create', :id => '567'
163 should_route :post, "/news/567/comments", :controller => 'comments', :action => 'create', :id => '567'
164
164
165 should_route :put, "/news/567", :controller => 'news', :action => 'update', :id => '567'
165 should_route :put, "/news/567", :controller => 'news', :action => 'update', :id => '567'
166
166
167 should_route :delete, "/news/567", :controller => 'news', :action => 'destroy', :id => '567'
167 should_route :delete, "/news/567", :controller => 'news', :action => 'destroy', :id => '567'
168 should_route :delete, "/news/567/comments/15", :controller => 'comments', :action => 'destroy', :id => '567', :comment_id => '15'
168 should_route :delete, "/news/567/comments/15", :controller => 'comments', :action => 'destroy', :id => '567', :comment_id => '15'
169 end
169 end
170
170
171 context "projects" do
171 context "projects" do
172 should_route :get, "/projects", :controller => 'projects', :action => 'index'
172 should_route :get, "/projects", :controller => 'projects', :action => 'index'
173 should_route :get, "/projects.atom", :controller => 'projects', :action => 'index', :format => 'atom'
173 should_route :get, "/projects.atom", :controller => 'projects', :action => 'index', :format => 'atom'
174 should_route :get, "/projects.xml", :controller => 'projects', :action => 'index', :format => 'xml'
174 should_route :get, "/projects.xml", :controller => 'projects', :action => 'index', :format => 'xml'
175 should_route :get, "/projects/new", :controller => 'projects', :action => 'new'
175 should_route :get, "/projects/new", :controller => 'projects', :action => 'new'
176 should_route :get, "/projects/test", :controller => 'projects', :action => 'show', :id => 'test'
176 should_route :get, "/projects/test", :controller => 'projects', :action => 'show', :id => 'test'
177 should_route :get, "/projects/1.xml", :controller => 'projects', :action => 'show', :id => '1', :format => 'xml'
177 should_route :get, "/projects/1.xml", :controller => 'projects', :action => 'show', :id => '1', :format => 'xml'
178 should_route :get, "/projects/4223/settings", :controller => 'projects', :action => 'settings', :id => '4223'
178 should_route :get, "/projects/4223/settings", :controller => 'projects', :action => 'settings', :id => '4223'
179 should_route :get, "/projects/4223/settings/members", :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members'
179 should_route :get, "/projects/4223/settings/members", :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members'
180 should_route :get, "/projects/33/files", :controller => 'files', :action => 'index', :project_id => '33'
180 should_route :get, "/projects/33/files", :controller => 'files', :action => 'index', :project_id => '33'
181 should_route :get, "/projects/33/files/new", :controller => 'files', :action => 'new', :project_id => '33'
181 should_route :get, "/projects/33/files/new", :controller => 'files', :action => 'new', :project_id => '33'
182 should_route :get, "/projects/33/roadmap", :controller => 'versions', :action => 'index', :project_id => '33'
182 should_route :get, "/projects/33/roadmap", :controller => 'versions', :action => 'index', :project_id => '33'
183 should_route :get, "/projects/33/activity", :controller => 'activities', :action => 'index', :id => '33'
183 should_route :get, "/projects/33/activity", :controller => 'activities', :action => 'index', :id => '33'
184 should_route :get, "/projects/33/activity.atom", :controller => 'activities', :action => 'index', :id => '33', :format => 'atom'
184 should_route :get, "/projects/33/activity.atom", :controller => 'activities', :action => 'index', :id => '33', :format => 'atom'
185
185
186 should_route :post, "/projects", :controller => 'projects', :action => 'create'
186 should_route :post, "/projects", :controller => 'projects', :action => 'create'
187 should_route :post, "/projects.xml", :controller => 'projects', :action => 'create', :format => 'xml'
187 should_route :post, "/projects.xml", :controller => 'projects', :action => 'create', :format => 'xml'
188 should_route :post, "/projects/33/files", :controller => 'files', :action => 'create', :project_id => '33'
188 should_route :post, "/projects/33/files", :controller => 'files', :action => 'create', :project_id => '33'
189 should_route :post, "/projects/64/archive", :controller => 'projects', :action => 'archive', :id => '64'
189 should_route :post, "/projects/64/archive", :controller => 'projects', :action => 'archive', :id => '64'
190 should_route :post, "/projects/64/unarchive", :controller => 'projects', :action => 'unarchive', :id => '64'
190 should_route :post, "/projects/64/unarchive", :controller => 'projects', :action => 'unarchive', :id => '64'
191
191
192 should_route :put, "/projects/64/enumerations", :controller => 'project_enumerations', :action => 'update', :project_id => '64'
192 should_route :put, "/projects/64/enumerations", :controller => 'project_enumerations', :action => 'update', :project_id => '64'
193 should_route :put, "/projects/4223", :controller => 'projects', :action => 'update', :id => '4223'
193 should_route :put, "/projects/4223", :controller => 'projects', :action => 'update', :id => '4223'
194 should_route :put, "/projects/1.xml", :controller => 'projects', :action => 'update', :id => '1', :format => 'xml'
194 should_route :put, "/projects/1.xml", :controller => 'projects', :action => 'update', :id => '1', :format => 'xml'
195
195
196 should_route :delete, "/projects/64", :controller => 'projects', :action => 'destroy', :id => '64'
196 should_route :delete, "/projects/64", :controller => 'projects', :action => 'destroy', :id => '64'
197 should_route :delete, "/projects/1.xml", :controller => 'projects', :action => 'destroy', :id => '1', :format => 'xml'
197 should_route :delete, "/projects/1.xml", :controller => 'projects', :action => 'destroy', :id => '1', :format => 'xml'
198 should_route :delete, "/projects/64/enumerations", :controller => 'project_enumerations', :action => 'destroy', :project_id => '64'
198 should_route :delete, "/projects/64/enumerations", :controller => 'project_enumerations', :action => 'destroy', :project_id => '64'
199 end
199 end
200
200
201 context "repositories" do
201 context "repositories" do
202 should_route :get, "/projects/redmine/repository", :controller => 'repositories', :action => 'show', :id => 'redmine'
202 should_route :get, "/projects/redmine/repository", :controller => 'repositories', :action => 'show', :id => 'redmine'
203 should_route :get, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
203 should_route :get, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
204 should_route :get, "/projects/redmine/repository/revisions", :controller => 'repositories', :action => 'revisions', :id => 'redmine'
204 should_route :get, "/projects/redmine/repository/revisions", :controller => 'repositories', :action => 'revisions', :id => 'redmine'
205 should_route :get, "/projects/redmine/repository/revisions.atom", :controller => 'repositories', :action => 'revisions', :id => 'redmine', :format => 'atom'
205 should_route :get, "/projects/redmine/repository/revisions.atom", :controller => 'repositories', :action => 'revisions', :id => 'redmine', :format => 'atom'
206 should_route :get, "/projects/redmine/repository/revisions/2457", :controller => 'repositories', :action => 'revision', :id => 'redmine', :rev => '2457'
206 should_route :get, "/projects/redmine/repository/revisions/2457", :controller => 'repositories', :action => 'revision', :id => 'redmine', :rev => '2457'
207 should_route :get, "/projects/redmine/repository/revisions/2457/diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457'
207 should_route :get, "/projects/redmine/repository/revisions/2457/diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457'
208 should_route :get, "/projects/redmine/repository/revisions/2457/diff.diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457', :format => 'diff'
208 should_route :get, "/projects/redmine/repository/revisions/2457/diff.diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457', :format => 'diff'
209 should_route :get, "/projects/redmine/repository/diff/path/to/file.c", :controller => 'repositories', :action => 'diff', :id => 'redmine', :path => %w[path to file.c]
209 should_route :get, "/projects/redmine/repository/diff/path/to/file.c", :controller => 'repositories', :action => 'diff', :id => 'redmine', :path => %w[path to file.c]
210 should_route :get, "/projects/redmine/repository/revisions/2/diff/path/to/file.c", :controller => 'repositories', :action => 'diff', :id => 'redmine', :path => %w[path to file.c], :rev => '2'
210 should_route :get, "/projects/redmine/repository/revisions/2/diff/path/to/file.c", :controller => 'repositories', :action => 'diff', :id => 'redmine', :path => %w[path to file.c], :rev => '2'
211 should_route :get, "/projects/redmine/repository/browse/path/to/file.c", :controller => 'repositories', :action => 'browse', :id => 'redmine', :path => %w[path to file.c]
211 should_route :get, "/projects/redmine/repository/browse/path/to/file.c", :controller => 'repositories', :action => 'browse', :id => 'redmine', :path => %w[path to file.c]
212 should_route :get, "/projects/redmine/repository/entry/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c]
212 should_route :get, "/projects/redmine/repository/entry/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c]
213 should_route :get, "/projects/redmine/repository/revisions/2/entry/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :rev => '2'
213 should_route :get, "/projects/redmine/repository/revisions/2/entry/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :rev => '2'
214 should_route :get, "/projects/redmine/repository/raw/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :format => 'raw'
214 should_route :get, "/projects/redmine/repository/raw/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :format => 'raw'
215 should_route :get, "/projects/redmine/repository/revisions/2/raw/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :rev => '2', :format => 'raw'
215 should_route :get, "/projects/redmine/repository/revisions/2/raw/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :rev => '2', :format => 'raw'
216 should_route :get, "/projects/redmine/repository/annotate/path/to/file.c", :controller => 'repositories', :action => 'annotate', :id => 'redmine', :path => %w[path to file.c]
216 should_route :get, "/projects/redmine/repository/annotate/path/to/file.c", :controller => 'repositories', :action => 'annotate', :id => 'redmine', :path => %w[path to file.c]
217 should_route :get, "/projects/redmine/repository/changes/path/to/file.c", :controller => 'repositories', :action => 'changes', :id => 'redmine', :path => %w[path to file.c]
217 should_route :get, "/projects/redmine/repository/changes/path/to/file.c", :controller => 'repositories', :action => 'changes', :id => 'redmine', :path => %w[path to file.c]
218 should_route :get, "/projects/redmine/repository/statistics", :controller => 'repositories', :action => 'stats', :id => 'redmine'
218 should_route :get, "/projects/redmine/repository/statistics", :controller => 'repositories', :action => 'stats', :id => 'redmine'
219
219
220
220
221 should_route :post, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
221 should_route :post, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
222 end
222 end
223
223
224 context "timelogs (global)" do
224 context "timelogs (global)" do
225 should_route :get, "/time_entries", :controller => 'timelog', :action => 'index'
225 should_route :get, "/time_entries", :controller => 'timelog', :action => 'index'
226 should_route :get, "/time_entries.csv", :controller => 'timelog', :action => 'index', :format => 'csv'
226 should_route :get, "/time_entries.csv", :controller => 'timelog', :action => 'index', :format => 'csv'
227 should_route :get, "/time_entries.atom", :controller => 'timelog', :action => 'index', :format => 'atom'
227 should_route :get, "/time_entries.atom", :controller => 'timelog', :action => 'index', :format => 'atom'
228 should_route :get, "/time_entries/new", :controller => 'timelog', :action => 'new'
228 should_route :get, "/time_entries/new", :controller => 'timelog', :action => 'new'
229 should_route :get, "/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22'
229 should_route :get, "/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22'
230
230
231 should_route :post, "/time_entries", :controller => 'timelog', :action => 'create'
231 should_route :post, "/time_entries", :controller => 'timelog', :action => 'create'
232
232
233 should_route :put, "/time_entries/22", :controller => 'timelog', :action => 'update', :id => '22'
233 should_route :put, "/time_entries/22", :controller => 'timelog', :action => 'update', :id => '22'
234
234
235 should_route :delete, "/time_entries/55", :controller => 'timelog', :action => 'destroy', :id => '55'
235 should_route :delete, "/time_entries/55", :controller => 'timelog', :action => 'destroy', :id => '55'
236 end
236 end
237
237
238 context "timelogs (scoped under project)" do
238 context "timelogs (scoped under project)" do
239 should_route :get, "/projects/567/time_entries", :controller => 'timelog', :action => 'index', :project_id => '567'
239 should_route :get, "/projects/567/time_entries", :controller => 'timelog', :action => 'index', :project_id => '567'
240 should_route :get, "/projects/567/time_entries.csv", :controller => 'timelog', :action => 'index', :project_id => '567', :format => 'csv'
240 should_route :get, "/projects/567/time_entries.csv", :controller => 'timelog', :action => 'index', :project_id => '567', :format => 'csv'
241 should_route :get, "/projects/567/time_entries.atom", :controller => 'timelog', :action => 'index', :project_id => '567', :format => 'atom'
241 should_route :get, "/projects/567/time_entries.atom", :controller => 'timelog', :action => 'index', :project_id => '567', :format => 'atom'
242 should_route :get, "/projects/567/time_entries/new", :controller => 'timelog', :action => 'new', :project_id => '567'
242 should_route :get, "/projects/567/time_entries/new", :controller => 'timelog', :action => 'new', :project_id => '567'
243 should_route :get, "/projects/567/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22', :project_id => '567'
243 should_route :get, "/projects/567/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22', :project_id => '567'
244
244
245 should_route :post, "/projects/567/time_entries", :controller => 'timelog', :action => 'create', :project_id => '567'
245 should_route :post, "/projects/567/time_entries", :controller => 'timelog', :action => 'create', :project_id => '567'
246
246
247 should_route :put, "/projects/567/time_entries/22", :controller => 'timelog', :action => 'update', :id => '22', :project_id => '567'
247 should_route :put, "/projects/567/time_entries/22", :controller => 'timelog', :action => 'update', :id => '22', :project_id => '567'
248
248
249 should_route :delete, "/projects/567/time_entries/55", :controller => 'timelog', :action => 'destroy', :id => '55', :project_id => '567'
249 should_route :delete, "/projects/567/time_entries/55", :controller => 'timelog', :action => 'destroy', :id => '55', :project_id => '567'
250 end
250 end
251
251
252 context "timelogs (scoped under issues)" do
252 context "timelogs (scoped under issues)" do
253 should_route :get, "/issues/234/time_entries", :controller => 'timelog', :action => 'index', :issue_id => '234'
253 should_route :get, "/issues/234/time_entries", :controller => 'timelog', :action => 'index', :issue_id => '234'
254 should_route :get, "/issues/234/time_entries.csv", :controller => 'timelog', :action => 'index', :issue_id => '234', :format => 'csv'
254 should_route :get, "/issues/234/time_entries.csv", :controller => 'timelog', :action => 'index', :issue_id => '234', :format => 'csv'
255 should_route :get, "/issues/234/time_entries.atom", :controller => 'timelog', :action => 'index', :issue_id => '234', :format => 'atom'
255 should_route :get, "/issues/234/time_entries.atom", :controller => 'timelog', :action => 'index', :issue_id => '234', :format => 'atom'
256 should_route :get, "/issues/234/time_entries/new", :controller => 'timelog', :action => 'new', :issue_id => '234'
256 should_route :get, "/issues/234/time_entries/new", :controller => 'timelog', :action => 'new', :issue_id => '234'
257 should_route :get, "/issues/234/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22', :issue_id => '234'
257 should_route :get, "/issues/234/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22', :issue_id => '234'
258
258
259 should_route :post, "/issues/234/time_entries", :controller => 'timelog', :action => 'create', :issue_id => '234'
259 should_route :post, "/issues/234/time_entries", :controller => 'timelog', :action => 'create', :issue_id => '234'
260
260
261 should_route :put, "/issues/234/time_entries/22", :controller => 'timelog', :action => 'update', :id => '22', :issue_id => '234'
261 should_route :put, "/issues/234/time_entries/22", :controller => 'timelog', :action => 'update', :id => '22', :issue_id => '234'
262
262
263 should_route :delete, "/issues/234/time_entries/55", :controller => 'timelog', :action => 'destroy', :id => '55', :issue_id => '234'
263 should_route :delete, "/issues/234/time_entries/55", :controller => 'timelog', :action => 'destroy', :id => '55', :issue_id => '234'
264 end
264 end
265
265
266 context "timelogs (scoped under project and issues)" do
266 context "timelogs (scoped under project and issues)" do
267 should_route :get, "/projects/ecookbook/issues/234/time_entries", :controller => 'timelog', :action => 'index', :issue_id => '234', :project_id => 'ecookbook'
267 should_route :get, "/projects/ecookbook/issues/234/time_entries", :controller => 'timelog', :action => 'index', :issue_id => '234', :project_id => 'ecookbook'
268 should_route :get, "/projects/ecookbook/issues/234/time_entries.csv", :controller => 'timelog', :action => 'index', :issue_id => '234', :project_id => 'ecookbook', :format => 'csv'
268 should_route :get, "/projects/ecookbook/issues/234/time_entries.csv", :controller => 'timelog', :action => 'index', :issue_id => '234', :project_id => 'ecookbook', :format => 'csv'
269 should_route :get, "/projects/ecookbook/issues/234/time_entries.atom", :controller => 'timelog', :action => 'index', :issue_id => '234', :project_id => 'ecookbook', :format => 'atom'
269 should_route :get, "/projects/ecookbook/issues/234/time_entries.atom", :controller => 'timelog', :action => 'index', :issue_id => '234', :project_id => 'ecookbook', :format => 'atom'
270 should_route :get, "/projects/ecookbook/issues/234/time_entries/new", :controller => 'timelog', :action => 'new', :issue_id => '234', :project_id => 'ecookbook'
270 should_route :get, "/projects/ecookbook/issues/234/time_entries/new", :controller => 'timelog', :action => 'new', :issue_id => '234', :project_id => 'ecookbook'
271 should_route :get, "/projects/ecookbook/issues/234/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22', :issue_id => '234', :project_id => 'ecookbook'
271 should_route :get, "/projects/ecookbook/issues/234/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22', :issue_id => '234', :project_id => 'ecookbook'
272
272
273 should_route :post, "/projects/ecookbook/issues/234/time_entries", :controller => 'timelog', :action => 'create', :issue_id => '234', :project_id => 'ecookbook'
273 should_route :post, "/projects/ecookbook/issues/234/time_entries", :controller => 'timelog', :action => 'create', :issue_id => '234', :project_id => 'ecookbook'
274
274
275 should_route :put, "/projects/ecookbook/issues/234/time_entries/22", :controller => 'timelog', :action => 'update', :id => '22', :issue_id => '234', :project_id => 'ecookbook'
275 should_route :put, "/projects/ecookbook/issues/234/time_entries/22", :controller => 'timelog', :action => 'update', :id => '22', :issue_id => '234', :project_id => 'ecookbook'
276
276
277 should_route :delete, "/projects/ecookbook/issues/234/time_entries/55", :controller => 'timelog', :action => 'destroy', :id => '55', :issue_id => '234', :project_id => 'ecookbook'
277 should_route :delete, "/projects/ecookbook/issues/234/time_entries/55", :controller => 'timelog', :action => 'destroy', :id => '55', :issue_id => '234', :project_id => 'ecookbook'
278 end
278 end
279
279
280 context "time_entry_reports" do
280 context "time_entry_reports" do
281 should_route :get, "/time_entries/report", :controller => 'time_entry_reports', :action => 'report'
281 should_route :get, "/time_entries/report", :controller => 'time_entry_reports', :action => 'report'
282 should_route :get, "/projects/567/time_entries/report", :controller => 'time_entry_reports', :action => 'report', :project_id => '567'
282 should_route :get, "/projects/567/time_entries/report", :controller => 'time_entry_reports', :action => 'report', :project_id => '567'
283 should_route :get, "/projects/567/time_entries/report.csv", :controller => 'time_entry_reports', :action => 'report', :project_id => '567', :format => 'csv'
283 should_route :get, "/projects/567/time_entries/report.csv", :controller => 'time_entry_reports', :action => 'report', :project_id => '567', :format => 'csv'
284 end
284 end
285
285
286 context "users" do
286 context "users" do
287 should_route :get, "/users", :controller => 'users', :action => 'index'
287 should_route :get, "/users", :controller => 'users', :action => 'index'
288 should_route :get, "/users/44", :controller => 'users', :action => 'show', :id => '44'
288 should_route :get, "/users/44", :controller => 'users', :action => 'show', :id => '44'
289 should_route :get, "/users/new", :controller => 'users', :action => 'new'
289 should_route :get, "/users/new", :controller => 'users', :action => 'new'
290 should_route :get, "/users/444/edit", :controller => 'users', :action => 'edit', :id => '444'
290 should_route :get, "/users/444/edit", :controller => 'users', :action => 'edit', :id => '444'
291 should_route :get, "/users/222/edit/membership", :controller => 'users', :action => 'edit', :id => '222', :tab => 'membership'
291 should_route :get, "/users/222/edit/membership", :controller => 'users', :action => 'edit', :id => '222', :tab => 'membership'
292
292
293 should_route :post, "/users", :controller => 'users', :action => 'create'
293 should_route :post, "/users", :controller => 'users', :action => 'create'
294 should_route :post, "/users/123/memberships", :controller => 'users', :action => 'edit_membership', :id => '123'
294 should_route :post, "/users/123/memberships", :controller => 'users', :action => 'edit_membership', :id => '123'
295 should_route :post, "/users/123/memberships/55", :controller => 'users', :action => 'edit_membership', :id => '123', :membership_id => '55'
295 should_route :post, "/users/123/memberships/55", :controller => 'users', :action => 'edit_membership', :id => '123', :membership_id => '55'
296 should_route :post, "/users/567/memberships/12/destroy", :controller => 'users', :action => 'destroy_membership', :id => '567', :membership_id => '12'
296 should_route :post, "/users/567/memberships/12/destroy", :controller => 'users', :action => 'destroy_membership', :id => '567', :membership_id => '12'
297
297
298 should_route :put, "/users/444", :controller => 'users', :action => 'update', :id => '444'
298 should_route :put, "/users/444", :controller => 'users', :action => 'update', :id => '444'
299 end
299 end
300
300
301 # TODO: should they all be scoped under /projects/:project_id ?
301 # TODO: should they all be scoped under /projects/:project_id ?
302 context "versions" do
302 context "versions" do
303 should_route :get, "/projects/foo/versions/new", :controller => 'versions', :action => 'new', :project_id => 'foo'
303 should_route :get, "/projects/foo/versions/new", :controller => 'versions', :action => 'new', :project_id => 'foo'
304 should_route :get, "/versions/show/1", :controller => 'versions', :action => 'show', :id => '1'
304 should_route :get, "/versions/show/1", :controller => 'versions', :action => 'show', :id => '1'
305 should_route :get, "/versions/edit/1", :controller => 'versions', :action => 'edit', :id => '1'
305 should_route :get, "/versions/edit/1", :controller => 'versions', :action => 'edit', :id => '1'
306
306
307 should_route :post, "/projects/foo/versions", :controller => 'versions', :action => 'create', :project_id => 'foo'
307 should_route :post, "/projects/foo/versions", :controller => 'versions', :action => 'create', :project_id => 'foo'
308 should_route :post, "/versions/update/1", :controller => 'versions', :action => 'update', :id => '1'
308 should_route :post, "/versions/update/1", :controller => 'versions', :action => 'update', :id => '1'
309
309
310 should_route :delete, "/versions/destroy/1", :controller => 'versions', :action => 'destroy', :id => '1'
310 should_route :delete, "/versions/destroy/1", :controller => 'versions', :action => 'destroy', :id => '1'
311 end
311 end
312
312
313 context "wiki (singular, project's pages)" do
313 context "wiki (singular, project's pages)" do
314 should_route :get, "/projects/567/wiki", :controller => 'wiki', :action => 'index', :id => '567'
314 should_route :get, "/projects/567/wiki", :controller => 'wiki', :action => 'index', :project_id => '567'
315 should_route :get, "/projects/567/wiki/lalala", :controller => 'wiki', :action => 'index', :id => '567', :page => 'lalala'
315 should_route :get, "/projects/567/wiki/lalala", :controller => 'wiki', :action => 'index', :project_id => '567', :page => 'lalala'
316 should_route :get, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :id => '567', :page => 'my_page'
316 should_route :get, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :project_id => '567', :page => 'my_page'
317 should_route :get, "/projects/1/wiki/CookBook_documentation/history", :controller => 'wiki', :action => 'history', :id => '1', :page => 'CookBook_documentation'
317 should_route :get, "/projects/1/wiki/CookBook_documentation/history", :controller => 'wiki', :action => 'history', :project_id => '1', :page => 'CookBook_documentation'
318 should_route :get, "/projects/1/wiki/CookBook_documentation/diff/2/vs/1", :controller => 'wiki', :action => 'diff', :id => '1', :page => 'CookBook_documentation', :version => '2', :version_from => '1'
318 should_route :get, "/projects/1/wiki/CookBook_documentation/diff/2/vs/1", :controller => 'wiki', :action => 'diff', :project_id => '1', :page => 'CookBook_documentation', :version => '2', :version_from => '1'
319 should_route :get, "/projects/1/wiki/CookBook_documentation/annotate/2", :controller => 'wiki', :action => 'annotate', :id => '1', :page => 'CookBook_documentation', :version => '2'
319 should_route :get, "/projects/1/wiki/CookBook_documentation/annotate/2", :controller => 'wiki', :action => 'annotate', :project_id => '1', :page => 'CookBook_documentation', :version => '2'
320 should_route :get, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :id => '22', :page => 'ladida'
320 should_route :get, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :project_id => '22', :page => 'ladida'
321 should_route :get, "/projects/567/wiki/page_index", :controller => 'wiki', :action => 'page_index', :id => '567'
321 should_route :get, "/projects/567/wiki/page_index", :controller => 'wiki', :action => 'page_index', :project_id => '567'
322 should_route :get, "/projects/567/wiki/date_index", :controller => 'wiki', :action => 'date_index', :id => '567'
322 should_route :get, "/projects/567/wiki/date_index", :controller => 'wiki', :action => 'date_index', :project_id => '567'
323 should_route :get, "/projects/567/wiki/export", :controller => 'wiki', :action => 'export', :id => '567'
323 should_route :get, "/projects/567/wiki/export", :controller => 'wiki', :action => 'export', :project_id => '567'
324
324
325 should_route :post, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :id => '567', :page => 'my_page'
325 should_route :post, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :project_id => '567', :page => 'my_page'
326 should_route :post, "/projects/567/wiki/CookBook_documentation/preview", :controller => 'wiki', :action => 'preview', :id => '567', :page => 'CookBook_documentation'
326 should_route :post, "/projects/567/wiki/CookBook_documentation/preview", :controller => 'wiki', :action => 'preview', :project_id => '567', :page => 'CookBook_documentation'
327 should_route :post, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :id => '22', :page => 'ladida'
327 should_route :post, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :project_id => '22', :page => 'ladida'
328 should_route :post, "/projects/22/wiki/ladida/destroy", :controller => 'wiki', :action => 'destroy', :id => '22', :page => 'ladida'
328 should_route :post, "/projects/22/wiki/ladida/destroy", :controller => 'wiki', :action => 'destroy', :project_id => '22', :page => 'ladida'
329 should_route :post, "/projects/22/wiki/ladida/protect", :controller => 'wiki', :action => 'protect', :id => '22', :page => 'ladida'
329 should_route :post, "/projects/22/wiki/ladida/protect", :controller => 'wiki', :action => 'protect', :project_id => '22', :page => 'ladida'
330 end
330 end
331
331
332 context "wikis (plural, admin setup)" do
332 context "wikis (plural, admin setup)" do
333 should_route :get, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
333 should_route :get, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
334
334
335 should_route :post, "/projects/ladida/wiki", :controller => 'wikis', :action => 'edit', :id => 'ladida'
335 should_route :post, "/projects/ladida/wiki", :controller => 'wikis', :action => 'edit', :id => 'ladida'
336 should_route :post, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
336 should_route :post, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
337 end
337 end
338
338
339 context "administration panel" do
339 context "administration panel" do
340 should_route :get, "/admin/projects", :controller => 'admin', :action => 'projects'
340 should_route :get, "/admin/projects", :controller => 'admin', :action => 'projects'
341 end
341 end
342 end
342 end
General Comments 0
You need to be logged in to leave comments. Login now