##// END OF EJS Templates
Removes calls to TimeZone#adjust (#1584)....
Jean-Philippe Lang -
r1612:1e6b8a482ae1
parent child
Show More
@@ -1,517 +1,513
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 'coderay'
18 require 'coderay'
19 require 'coderay/helpers/file_type'
19 require 'coderay/helpers/file_type'
20
20
21 module ApplicationHelper
21 module ApplicationHelper
22 include Redmine::WikiFormatting::Macros::Definitions
22 include Redmine::WikiFormatting::Macros::Definitions
23
23
24 def current_role
24 def current_role
25 @current_role ||= User.current.role_for_project(@project)
25 @current_role ||= User.current.role_for_project(@project)
26 end
26 end
27
27
28 # Return true if user is authorized for controller/action, otherwise false
28 # Return true if user is authorized for controller/action, otherwise false
29 def authorize_for(controller, action)
29 def authorize_for(controller, action)
30 User.current.allowed_to?({:controller => controller, :action => action}, @project)
30 User.current.allowed_to?({:controller => controller, :action => action}, @project)
31 end
31 end
32
32
33 # Display a link if user is authorized
33 # Display a link if user is authorized
34 def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
34 def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
35 link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action])
35 link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action])
36 end
36 end
37
37
38 # Display a link to user's account page
38 # Display a link to user's account page
39 def link_to_user(user)
39 def link_to_user(user)
40 user ? link_to(user, :controller => 'account', :action => 'show', :id => user) : 'Anonymous'
40 user ? link_to(user, :controller => 'account', :action => 'show', :id => user) : 'Anonymous'
41 end
41 end
42
42
43 def link_to_issue(issue, options={})
43 def link_to_issue(issue, options={})
44 link_to "#{issue.tracker.name} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue}, options
44 link_to "#{issue.tracker.name} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue}, options
45 end
45 end
46
46
47 def toggle_link(name, id, options={})
47 def toggle_link(name, id, options={})
48 onclick = "Element.toggle('#{id}'); "
48 onclick = "Element.toggle('#{id}'); "
49 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
49 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
50 onclick << "return false;"
50 onclick << "return false;"
51 link_to(name, "#", :onclick => onclick)
51 link_to(name, "#", :onclick => onclick)
52 end
52 end
53
53
54 def image_to_function(name, function, html_options = {})
54 def image_to_function(name, function, html_options = {})
55 html_options.symbolize_keys!
55 html_options.symbolize_keys!
56 tag(:input, html_options.merge({
56 tag(:input, html_options.merge({
57 :type => "image", :src => image_path(name),
57 :type => "image", :src => image_path(name),
58 :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
58 :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
59 }))
59 }))
60 end
60 end
61
61
62 def prompt_to_remote(name, text, param, url, html_options = {})
62 def prompt_to_remote(name, text, param, url, html_options = {})
63 html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;"
63 html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;"
64 link_to name, {}, html_options
64 link_to name, {}, html_options
65 end
65 end
66
66
67 def format_date(date)
67 def format_date(date)
68 return nil unless date
68 return nil unless date
69 # "Setting.date_format.size < 2" is a temporary fix (content of date_format setting changed)
69 # "Setting.date_format.size < 2" is a temporary fix (content of date_format setting changed)
70 @date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
70 @date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
71 date.strftime(@date_format)
71 date.strftime(@date_format)
72 end
72 end
73
73
74 def format_time(time, include_date = true)
74 def format_time(time, include_date = true)
75 return nil unless time
75 return nil unless time
76 time = time.to_time if time.is_a?(String)
76 time = time.to_time if time.is_a?(String)
77 zone = User.current.time_zone
77 zone = User.current.time_zone
78 if time.utc?
78 local = zone ? time.in_time_zone(zone) : (time.utc? ? time.utc_to_local : time)
79 local = zone ? zone.adjust(time) : time.getlocal
80 else
81 local = zone ? zone.adjust(time.getutc) : time
82 end
83 @date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
79 @date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
84 @time_format ||= (Setting.time_format.blank? ? l(:general_fmt_time) : Setting.time_format)
80 @time_format ||= (Setting.time_format.blank? ? l(:general_fmt_time) : Setting.time_format)
85 include_date ? local.strftime("#{@date_format} #{@time_format}") : local.strftime(@time_format)
81 include_date ? local.strftime("#{@date_format} #{@time_format}") : local.strftime(@time_format)
86 end
82 end
87
83
88 # Truncates and returns the string as a single line
84 # Truncates and returns the string as a single line
89 def truncate_single_line(string, *args)
85 def truncate_single_line(string, *args)
90 truncate(string, *args).gsub(%r{[\r\n]+}m, ' ')
86 truncate(string, *args).gsub(%r{[\r\n]+}m, ' ')
91 end
87 end
92
88
93 def html_hours(text)
89 def html_hours(text)
94 text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>')
90 text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>')
95 end
91 end
96
92
97 def authoring(created, author)
93 def authoring(created, author)
98 time_tag = content_tag('acronym', distance_of_time_in_words(Time.now, created), :title => format_time(created))
94 time_tag = content_tag('acronym', distance_of_time_in_words(Time.now, created), :title => format_time(created))
99 l(:label_added_time_by, author || 'Anonymous', time_tag)
95 l(:label_added_time_by, author || 'Anonymous', time_tag)
100 end
96 end
101
97
102 def l_or_humanize(s)
98 def l_or_humanize(s)
103 l_has_string?("label_#{s}".to_sym) ? l("label_#{s}".to_sym) : s.to_s.humanize
99 l_has_string?("label_#{s}".to_sym) ? l("label_#{s}".to_sym) : s.to_s.humanize
104 end
100 end
105
101
106 def day_name(day)
102 def day_name(day)
107 l(:general_day_names).split(',')[day-1]
103 l(:general_day_names).split(',')[day-1]
108 end
104 end
109
105
110 def month_name(month)
106 def month_name(month)
111 l(:actionview_datehelper_select_month_names).split(',')[month-1]
107 l(:actionview_datehelper_select_month_names).split(',')[month-1]
112 end
108 end
113
109
114 def syntax_highlight(name, content)
110 def syntax_highlight(name, content)
115 type = CodeRay::FileType[name]
111 type = CodeRay::FileType[name]
116 type ? CodeRay.scan(content, type).html : h(content)
112 type ? CodeRay.scan(content, type).html : h(content)
117 end
113 end
118
114
119 def pagination_links_full(paginator, count=nil, options={})
115 def pagination_links_full(paginator, count=nil, options={})
120 page_param = options.delete(:page_param) || :page
116 page_param = options.delete(:page_param) || :page
121 url_param = params.dup
117 url_param = params.dup
122 # don't reuse params if filters are present
118 # don't reuse params if filters are present
123 url_param.clear if url_param.has_key?(:set_filter)
119 url_param.clear if url_param.has_key?(:set_filter)
124
120
125 html = ''
121 html = ''
126 html << link_to_remote(('&#171; ' + l(:label_previous)),
122 html << link_to_remote(('&#171; ' + l(:label_previous)),
127 {:update => 'content',
123 {:update => 'content',
128 :url => url_param.merge(page_param => paginator.current.previous),
124 :url => url_param.merge(page_param => paginator.current.previous),
129 :complete => 'window.scrollTo(0,0)'},
125 :complete => 'window.scrollTo(0,0)'},
130 {:href => url_for(:params => url_param.merge(page_param => paginator.current.previous))}) + ' ' if paginator.current.previous
126 {:href => url_for(:params => url_param.merge(page_param => paginator.current.previous))}) + ' ' if paginator.current.previous
131
127
132 html << (pagination_links_each(paginator, options) do |n|
128 html << (pagination_links_each(paginator, options) do |n|
133 link_to_remote(n.to_s,
129 link_to_remote(n.to_s,
134 {:url => {:params => url_param.merge(page_param => n)},
130 {:url => {:params => url_param.merge(page_param => n)},
135 :update => 'content',
131 :update => 'content',
136 :complete => 'window.scrollTo(0,0)'},
132 :complete => 'window.scrollTo(0,0)'},
137 {:href => url_for(:params => url_param.merge(page_param => n))})
133 {:href => url_for(:params => url_param.merge(page_param => n))})
138 end || '')
134 end || '')
139
135
140 html << ' ' + link_to_remote((l(:label_next) + ' &#187;'),
136 html << ' ' + link_to_remote((l(:label_next) + ' &#187;'),
141 {:update => 'content',
137 {:update => 'content',
142 :url => url_param.merge(page_param => paginator.current.next),
138 :url => url_param.merge(page_param => paginator.current.next),
143 :complete => 'window.scrollTo(0,0)'},
139 :complete => 'window.scrollTo(0,0)'},
144 {:href => url_for(:params => url_param.merge(page_param => paginator.current.next))}) if paginator.current.next
140 {:href => url_for(:params => url_param.merge(page_param => paginator.current.next))}) if paginator.current.next
145
141
146 unless count.nil?
142 unless count.nil?
147 html << [" (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})", per_page_links(paginator.items_per_page)].compact.join(' | ')
143 html << [" (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})", per_page_links(paginator.items_per_page)].compact.join(' | ')
148 end
144 end
149
145
150 html
146 html
151 end
147 end
152
148
153 def per_page_links(selected=nil)
149 def per_page_links(selected=nil)
154 url_param = params.dup
150 url_param = params.dup
155 url_param.clear if url_param.has_key?(:set_filter)
151 url_param.clear if url_param.has_key?(:set_filter)
156
152
157 links = Setting.per_page_options_array.collect do |n|
153 links = Setting.per_page_options_array.collect do |n|
158 n == selected ? n : link_to_remote(n, {:update => "content", :url => params.dup.merge(:per_page => n)},
154 n == selected ? n : link_to_remote(n, {:update => "content", :url => params.dup.merge(:per_page => n)},
159 {:href => url_for(url_param.merge(:per_page => n))})
155 {:href => url_for(url_param.merge(:per_page => n))})
160 end
156 end
161 links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil
157 links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil
162 end
158 end
163
159
164 def breadcrumb(*args)
160 def breadcrumb(*args)
165 content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb')
161 content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb')
166 end
162 end
167
163
168 def html_title(*args)
164 def html_title(*args)
169 if args.empty?
165 if args.empty?
170 title = []
166 title = []
171 title << @project.name if @project
167 title << @project.name if @project
172 title += @html_title if @html_title
168 title += @html_title if @html_title
173 title << Setting.app_title
169 title << Setting.app_title
174 title.compact.join(' - ')
170 title.compact.join(' - ')
175 else
171 else
176 @html_title ||= []
172 @html_title ||= []
177 @html_title += args
173 @html_title += args
178 end
174 end
179 end
175 end
180
176
181 def accesskey(s)
177 def accesskey(s)
182 Redmine::AccessKeys.key_for s
178 Redmine::AccessKeys.key_for s
183 end
179 end
184
180
185 # Formats text according to system settings.
181 # Formats text according to system settings.
186 # 2 ways to call this method:
182 # 2 ways to call this method:
187 # * with a String: textilizable(text, options)
183 # * with a String: textilizable(text, options)
188 # * with an object and one of its attribute: textilizable(issue, :description, options)
184 # * with an object and one of its attribute: textilizable(issue, :description, options)
189 def textilizable(*args)
185 def textilizable(*args)
190 options = args.last.is_a?(Hash) ? args.pop : {}
186 options = args.last.is_a?(Hash) ? args.pop : {}
191 case args.size
187 case args.size
192 when 1
188 when 1
193 obj = nil
189 obj = nil
194 text = args.shift
190 text = args.shift
195 when 2
191 when 2
196 obj = args.shift
192 obj = args.shift
197 text = obj.send(args.shift).to_s
193 text = obj.send(args.shift).to_s
198 else
194 else
199 raise ArgumentError, 'invalid arguments to textilizable'
195 raise ArgumentError, 'invalid arguments to textilizable'
200 end
196 end
201 return '' if text.blank?
197 return '' if text.blank?
202
198
203 only_path = options.delete(:only_path) == false ? false : true
199 only_path = options.delete(:only_path) == false ? false : true
204
200
205 # when using an image link, try to use an attachment, if possible
201 # when using an image link, try to use an attachment, if possible
206 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
202 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
207
203
208 if attachments
204 if attachments
209 text = text.gsub(/!((\<|\=|\>)?(\([^\)]+\))?(\[[^\]]+\])?(\{[^\}]+\})?)(\S+\.(gif|jpg|jpeg|png))!/) do |m|
205 text = text.gsub(/!((\<|\=|\>)?(\([^\)]+\))?(\[[^\]]+\])?(\{[^\}]+\})?)(\S+\.(gif|jpg|jpeg|png))!/) do |m|
210 style = $1
206 style = $1
211 filename = $6
207 filename = $6
212 rf = Regexp.new(filename, Regexp::IGNORECASE)
208 rf = Regexp.new(filename, Regexp::IGNORECASE)
213 # search for the picture in attachments
209 # search for the picture in attachments
214 if found = attachments.detect { |att| att.filename =~ rf }
210 if found = attachments.detect { |att| att.filename =~ rf }
215 image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found
211 image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found
216 desc = found.description.to_s.gsub(/^([^\(\)]*).*$/, "\\1")
212 desc = found.description.to_s.gsub(/^([^\(\)]*).*$/, "\\1")
217 alt = desc.blank? ? nil : "(#{desc})"
213 alt = desc.blank? ? nil : "(#{desc})"
218 "!#{style}#{image_url}#{alt}!"
214 "!#{style}#{image_url}#{alt}!"
219 else
215 else
220 "!#{style}#{filename}!"
216 "!#{style}#{filename}!"
221 end
217 end
222 end
218 end
223 end
219 end
224
220
225 text = (Setting.text_formatting == 'textile') ?
221 text = (Setting.text_formatting == 'textile') ?
226 Redmine::WikiFormatting.to_html(text) { |macro, args| exec_macro(macro, obj, args) } :
222 Redmine::WikiFormatting.to_html(text) { |macro, args| exec_macro(macro, obj, args) } :
227 simple_format(auto_link(h(text)))
223 simple_format(auto_link(h(text)))
228
224
229 # different methods for formatting wiki links
225 # different methods for formatting wiki links
230 case options[:wiki_links]
226 case options[:wiki_links]
231 when :local
227 when :local
232 # used for local links to html files
228 # used for local links to html files
233 format_wiki_link = Proc.new {|project, title| "#{title}.html" }
229 format_wiki_link = Proc.new {|project, title| "#{title}.html" }
234 when :anchor
230 when :anchor
235 # used for single-file wiki export
231 # used for single-file wiki export
236 format_wiki_link = Proc.new {|project, title| "##{title}" }
232 format_wiki_link = Proc.new {|project, title| "##{title}" }
237 else
233 else
238 format_wiki_link = Proc.new {|project, title| url_for(:only_path => only_path, :controller => 'wiki', :action => 'index', :id => project, :page => title) }
234 format_wiki_link = Proc.new {|project, title| url_for(:only_path => only_path, :controller => 'wiki', :action => 'index', :id => project, :page => title) }
239 end
235 end
240
236
241 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
237 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
242
238
243 # Wiki links
239 # Wiki links
244 #
240 #
245 # Examples:
241 # Examples:
246 # [[mypage]]
242 # [[mypage]]
247 # [[mypage|mytext]]
243 # [[mypage|mytext]]
248 # wiki links can refer other project wikis, using project name or identifier:
244 # wiki links can refer other project wikis, using project name or identifier:
249 # [[project:]] -> wiki starting page
245 # [[project:]] -> wiki starting page
250 # [[project:|mytext]]
246 # [[project:|mytext]]
251 # [[project:mypage]]
247 # [[project:mypage]]
252 # [[project:mypage|mytext]]
248 # [[project:mypage|mytext]]
253 text = text.gsub(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m|
249 text = text.gsub(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m|
254 link_project = project
250 link_project = project
255 esc, all, page, title = $1, $2, $3, $5
251 esc, all, page, title = $1, $2, $3, $5
256 if esc.nil?
252 if esc.nil?
257 if page =~ /^([^\:]+)\:(.*)$/
253 if page =~ /^([^\:]+)\:(.*)$/
258 link_project = Project.find_by_name($1) || Project.find_by_identifier($1)
254 link_project = Project.find_by_name($1) || Project.find_by_identifier($1)
259 page = $2
255 page = $2
260 title ||= $1 if page.blank?
256 title ||= $1 if page.blank?
261 end
257 end
262
258
263 if link_project && link_project.wiki
259 if link_project && link_project.wiki
264 # check if page exists
260 # check if page exists
265 wiki_page = link_project.wiki.find_page(page)
261 wiki_page = link_project.wiki.find_page(page)
266 link_to((title || page), format_wiki_link.call(link_project, Wiki.titleize(page)),
262 link_to((title || page), format_wiki_link.call(link_project, Wiki.titleize(page)),
267 :class => ('wiki-page' + (wiki_page ? '' : ' new')))
263 :class => ('wiki-page' + (wiki_page ? '' : ' new')))
268 else
264 else
269 # project or wiki doesn't exist
265 # project or wiki doesn't exist
270 title || page
266 title || page
271 end
267 end
272 else
268 else
273 all
269 all
274 end
270 end
275 end
271 end
276
272
277 # Redmine links
273 # Redmine links
278 #
274 #
279 # Examples:
275 # Examples:
280 # Issues:
276 # Issues:
281 # #52 -> Link to issue #52
277 # #52 -> Link to issue #52
282 # Changesets:
278 # Changesets:
283 # r52 -> Link to revision 52
279 # r52 -> Link to revision 52
284 # commit:a85130f -> Link to scmid starting with a85130f
280 # commit:a85130f -> Link to scmid starting with a85130f
285 # Documents:
281 # Documents:
286 # document#17 -> Link to document with id 17
282 # document#17 -> Link to document with id 17
287 # document:Greetings -> Link to the document with title "Greetings"
283 # document:Greetings -> Link to the document with title "Greetings"
288 # document:"Some document" -> Link to the document with title "Some document"
284 # document:"Some document" -> Link to the document with title "Some document"
289 # Versions:
285 # Versions:
290 # version#3 -> Link to version with id 3
286 # version#3 -> Link to version with id 3
291 # version:1.0.0 -> Link to version named "1.0.0"
287 # version:1.0.0 -> Link to version named "1.0.0"
292 # version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
288 # version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
293 # Attachments:
289 # Attachments:
294 # attachment:file.zip -> Link to the attachment of the current object named file.zip
290 # attachment:file.zip -> Link to the attachment of the current object named file.zip
295 # Source files:
291 # Source files:
296 # source:some/file -> Link to the file located at /some/file in the project's repository
292 # source:some/file -> Link to the file located at /some/file in the project's repository
297 # source:some/file@52 -> Link to the file's revision 52
293 # source:some/file@52 -> Link to the file's revision 52
298 # source:some/file#L120 -> Link to line 120 of the file
294 # source:some/file#L120 -> Link to line 120 of the file
299 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
295 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
300 # export:some/file -> Force the download of the file
296 # export:some/file -> Force the download of the file
301 text = text.gsub(%r{([\s\(,\-\>]|^)(!)?(attachment|document|version|commit|source|export)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*|"[^"]+"))(?=[[:punct:]]|\s|<|$)}) do |m|
297 text = text.gsub(%r{([\s\(,\-\>]|^)(!)?(attachment|document|version|commit|source|export)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*|"[^"]+"))(?=[[:punct:]]|\s|<|$)}) do |m|
302 leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8
298 leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8
303 link = nil
299 link = nil
304 if esc.nil?
300 if esc.nil?
305 if prefix.nil? && sep == 'r'
301 if prefix.nil? && sep == 'r'
306 if project && (changeset = project.changesets.find_by_revision(oid))
302 if project && (changeset = project.changesets.find_by_revision(oid))
307 link = link_to("r#{oid}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => oid},
303 link = link_to("r#{oid}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => oid},
308 :class => 'changeset',
304 :class => 'changeset',
309 :title => truncate_single_line(changeset.comments, 100))
305 :title => truncate_single_line(changeset.comments, 100))
310 end
306 end
311 elsif sep == '#'
307 elsif sep == '#'
312 oid = oid.to_i
308 oid = oid.to_i
313 case prefix
309 case prefix
314 when nil
310 when nil
315 if issue = Issue.find_by_id(oid, :include => [:project, :status], :conditions => Project.visible_by(User.current))
311 if issue = Issue.find_by_id(oid, :include => [:project, :status], :conditions => Project.visible_by(User.current))
316 link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid},
312 link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid},
317 :class => (issue.closed? ? 'issue closed' : 'issue'),
313 :class => (issue.closed? ? 'issue closed' : 'issue'),
318 :title => "#{truncate(issue.subject, 100)} (#{issue.status.name})")
314 :title => "#{truncate(issue.subject, 100)} (#{issue.status.name})")
319 link = content_tag('del', link) if issue.closed?
315 link = content_tag('del', link) if issue.closed?
320 end
316 end
321 when 'document'
317 when 'document'
322 if document = Document.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
318 if document = Document.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
323 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
319 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
324 :class => 'document'
320 :class => 'document'
325 end
321 end
326 when 'version'
322 when 'version'
327 if version = Version.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
323 if version = Version.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
328 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
324 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
329 :class => 'version'
325 :class => 'version'
330 end
326 end
331 end
327 end
332 elsif sep == ':'
328 elsif sep == ':'
333 # removes the double quotes if any
329 # removes the double quotes if any
334 name = oid.gsub(%r{^"(.*)"$}, "\\1")
330 name = oid.gsub(%r{^"(.*)"$}, "\\1")
335 case prefix
331 case prefix
336 when 'document'
332 when 'document'
337 if project && document = project.documents.find_by_title(name)
333 if project && document = project.documents.find_by_title(name)
338 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
334 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
339 :class => 'document'
335 :class => 'document'
340 end
336 end
341 when 'version'
337 when 'version'
342 if project && version = project.versions.find_by_name(name)
338 if project && version = project.versions.find_by_name(name)
343 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
339 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
344 :class => 'version'
340 :class => 'version'
345 end
341 end
346 when 'commit'
342 when 'commit'
347 if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"]))
343 if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"]))
348 link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
344 link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
349 :class => 'changeset',
345 :class => 'changeset',
350 :title => truncate_single_line(changeset.comments, 100)
346 :title => truncate_single_line(changeset.comments, 100)
351 end
347 end
352 when 'source', 'export'
348 when 'source', 'export'
353 if project && project.repository
349 if project && project.repository
354 name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
350 name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
355 path, rev, anchor = $1, $3, $5
351 path, rev, anchor = $1, $3, $5
356 link = link_to h("#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project, :path => path,
352 link = link_to h("#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project, :path => path,
357 :rev => rev,
353 :rev => rev,
358 :anchor => anchor,
354 :anchor => anchor,
359 :format => (prefix == 'export' ? 'raw' : nil)},
355 :format => (prefix == 'export' ? 'raw' : nil)},
360 :class => (prefix == 'export' ? 'source download' : 'source')
356 :class => (prefix == 'export' ? 'source download' : 'source')
361 end
357 end
362 when 'attachment'
358 when 'attachment'
363 if attachments && attachment = attachments.detect {|a| a.filename == name }
359 if attachments && attachment = attachments.detect {|a| a.filename == name }
364 link = link_to h(attachment.filename), {:only_path => only_path, :controller => 'attachments', :action => 'download', :id => attachment},
360 link = link_to h(attachment.filename), {:only_path => only_path, :controller => 'attachments', :action => 'download', :id => attachment},
365 :class => 'attachment'
361 :class => 'attachment'
366 end
362 end
367 end
363 end
368 end
364 end
369 end
365 end
370 leading + (link || "#{prefix}#{sep}#{oid}")
366 leading + (link || "#{prefix}#{sep}#{oid}")
371 end
367 end
372
368
373 text
369 text
374 end
370 end
375
371
376 # Same as Rails' simple_format helper without using paragraphs
372 # Same as Rails' simple_format helper without using paragraphs
377 def simple_format_without_paragraph(text)
373 def simple_format_without_paragraph(text)
378 text.to_s.
374 text.to_s.
379 gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
375 gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
380 gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
376 gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
381 gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
377 gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
382 end
378 end
383
379
384 def error_messages_for(object_name, options = {})
380 def error_messages_for(object_name, options = {})
385 options = options.symbolize_keys
381 options = options.symbolize_keys
386 object = instance_variable_get("@#{object_name}")
382 object = instance_variable_get("@#{object_name}")
387 if object && !object.errors.empty?
383 if object && !object.errors.empty?
388 # build full_messages here with controller current language
384 # build full_messages here with controller current language
389 full_messages = []
385 full_messages = []
390 object.errors.each do |attr, msg|
386 object.errors.each do |attr, msg|
391 next if msg.nil?
387 next if msg.nil?
392 msg = msg.first if msg.is_a? Array
388 msg = msg.first if msg.is_a? Array
393 if attr == "base"
389 if attr == "base"
394 full_messages << l(msg)
390 full_messages << l(msg)
395 else
391 else
396 full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(msg) unless attr == "custom_values"
392 full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(msg) unless attr == "custom_values"
397 end
393 end
398 end
394 end
399 # retrieve custom values error messages
395 # retrieve custom values error messages
400 if object.errors[:custom_values]
396 if object.errors[:custom_values]
401 object.custom_values.each do |v|
397 object.custom_values.each do |v|
402 v.errors.each do |attr, msg|
398 v.errors.each do |attr, msg|
403 next if msg.nil?
399 next if msg.nil?
404 msg = msg.first if msg.is_a? Array
400 msg = msg.first if msg.is_a? Array
405 full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(msg)
401 full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(msg)
406 end
402 end
407 end
403 end
408 end
404 end
409 content_tag("div",
405 content_tag("div",
410 content_tag(
406 content_tag(
411 options[:header_tag] || "span", lwr(:gui_validation_error, full_messages.length) + ":"
407 options[:header_tag] || "span", lwr(:gui_validation_error, full_messages.length) + ":"
412 ) +
408 ) +
413 content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }),
409 content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }),
414 "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
410 "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
415 )
411 )
416 else
412 else
417 ""
413 ""
418 end
414 end
419 end
415 end
420
416
421 def lang_options_for_select(blank=true)
417 def lang_options_for_select(blank=true)
422 (blank ? [["(auto)", ""]] : []) +
418 (blank ? [["(auto)", ""]] : []) +
423 GLoc.valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.last <=> y.last }
419 GLoc.valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.last <=> y.last }
424 end
420 end
425
421
426 def label_tag_for(name, option_tags = nil, options = {})
422 def label_tag_for(name, option_tags = nil, options = {})
427 label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
423 label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
428 content_tag("label", label_text)
424 content_tag("label", label_text)
429 end
425 end
430
426
431 def labelled_tabular_form_for(name, object, options, &proc)
427 def labelled_tabular_form_for(name, object, options, &proc)
432 options[:html] ||= {}
428 options[:html] ||= {}
433 options[:html][:class] = 'tabular' unless options[:html].has_key?(:class)
429 options[:html][:class] = 'tabular' unless options[:html].has_key?(:class)
434 form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
430 form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
435 end
431 end
436
432
437 def back_url_hidden_field_tag
433 def back_url_hidden_field_tag
438 hidden_field_tag 'back_url', (params[:back_url] || request.env['HTTP_REFERER'])
434 hidden_field_tag 'back_url', (params[:back_url] || request.env['HTTP_REFERER'])
439 end
435 end
440
436
441 def check_all_links(form_name)
437 def check_all_links(form_name)
442 link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
438 link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
443 " | " +
439 " | " +
444 link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
440 link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
445 end
441 end
446
442
447 def progress_bar(pcts, options={})
443 def progress_bar(pcts, options={})
448 pcts = [pcts, pcts] unless pcts.is_a?(Array)
444 pcts = [pcts, pcts] unless pcts.is_a?(Array)
449 pcts[1] = pcts[1] - pcts[0]
445 pcts[1] = pcts[1] - pcts[0]
450 pcts << (100 - pcts[1] - pcts[0])
446 pcts << (100 - pcts[1] - pcts[0])
451 width = options[:width] || '100px;'
447 width = options[:width] || '100px;'
452 legend = options[:legend] || ''
448 legend = options[:legend] || ''
453 content_tag('table',
449 content_tag('table',
454 content_tag('tr',
450 content_tag('tr',
455 (pcts[0] > 0 ? content_tag('td', '', :width => "#{pcts[0].floor}%;", :class => 'closed') : '') +
451 (pcts[0] > 0 ? content_tag('td', '', :width => "#{pcts[0].floor}%;", :class => 'closed') : '') +
456 (pcts[1] > 0 ? content_tag('td', '', :width => "#{pcts[1].floor}%;", :class => 'done') : '') +
452 (pcts[1] > 0 ? content_tag('td', '', :width => "#{pcts[1].floor}%;", :class => 'done') : '') +
457 (pcts[2] > 0 ? content_tag('td', '', :width => "#{pcts[2].floor}%;", :class => 'todo') : '')
453 (pcts[2] > 0 ? content_tag('td', '', :width => "#{pcts[2].floor}%;", :class => 'todo') : '')
458 ), :class => 'progress', :style => "width: #{width};") +
454 ), :class => 'progress', :style => "width: #{width};") +
459 content_tag('p', legend, :class => 'pourcent')
455 content_tag('p', legend, :class => 'pourcent')
460 end
456 end
461
457
462 def context_menu_link(name, url, options={})
458 def context_menu_link(name, url, options={})
463 options[:class] ||= ''
459 options[:class] ||= ''
464 if options.delete(:selected)
460 if options.delete(:selected)
465 options[:class] << ' icon-checked disabled'
461 options[:class] << ' icon-checked disabled'
466 options[:disabled] = true
462 options[:disabled] = true
467 end
463 end
468 if options.delete(:disabled)
464 if options.delete(:disabled)
469 options.delete(:method)
465 options.delete(:method)
470 options.delete(:confirm)
466 options.delete(:confirm)
471 options.delete(:onclick)
467 options.delete(:onclick)
472 options[:class] << ' disabled'
468 options[:class] << ' disabled'
473 url = '#'
469 url = '#'
474 end
470 end
475 link_to name, url, options
471 link_to name, url, options
476 end
472 end
477
473
478 def calendar_for(field_id)
474 def calendar_for(field_id)
479 include_calendar_headers_tags
475 include_calendar_headers_tags
480 image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
476 image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
481 javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
477 javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
482 end
478 end
483
479
484 def include_calendar_headers_tags
480 def include_calendar_headers_tags
485 unless @calendar_headers_tags_included
481 unless @calendar_headers_tags_included
486 @calendar_headers_tags_included = true
482 @calendar_headers_tags_included = true
487 content_for :header_tags do
483 content_for :header_tags do
488 javascript_include_tag('calendar/calendar') +
484 javascript_include_tag('calendar/calendar') +
489 javascript_include_tag("calendar/lang/calendar-#{current_language}.js") +
485 javascript_include_tag("calendar/lang/calendar-#{current_language}.js") +
490 javascript_include_tag('calendar/calendar-setup') +
486 javascript_include_tag('calendar/calendar-setup') +
491 stylesheet_link_tag('calendar')
487 stylesheet_link_tag('calendar')
492 end
488 end
493 end
489 end
494 end
490 end
495
491
496 def wikitoolbar_for(field_id)
492 def wikitoolbar_for(field_id)
497 return '' unless Setting.text_formatting == 'textile'
493 return '' unless Setting.text_formatting == 'textile'
498
494
499 help_link = l(:setting_text_formatting) + ': ' +
495 help_link = l(:setting_text_formatting) + ': ' +
500 link_to(l(:label_help), compute_public_path('wiki_syntax', 'help', 'html'),
496 link_to(l(:label_help), compute_public_path('wiki_syntax', 'help', 'html'),
501 :onclick => "window.open(\"#{ compute_public_path('wiki_syntax', 'help', 'html') }\", \"\", \"resizable=yes, location=no, width=300, height=640, menubar=no, status=no, scrollbars=yes\"); return false;")
497 :onclick => "window.open(\"#{ compute_public_path('wiki_syntax', 'help', 'html') }\", \"\", \"resizable=yes, location=no, width=300, height=640, menubar=no, status=no, scrollbars=yes\"); return false;")
502
498
503 javascript_include_tag('jstoolbar/jstoolbar') +
499 javascript_include_tag('jstoolbar/jstoolbar') +
504 javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language}") +
500 javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language}") +
505 javascript_tag("var toolbar = new jsToolBar($('#{field_id}')); toolbar.setHelpLink('#{help_link}'); toolbar.draw();")
501 javascript_tag("var toolbar = new jsToolBar($('#{field_id}')); toolbar.setHelpLink('#{help_link}'); toolbar.draw();")
506 end
502 end
507
503
508 def content_for(name, content = nil, &block)
504 def content_for(name, content = nil, &block)
509 @has_content ||= {}
505 @has_content ||= {}
510 @has_content[name] = true
506 @has_content[name] = true
511 super(name, content, &block)
507 super(name, content, &block)
512 end
508 end
513
509
514 def has_content?(name)
510 def has_content?(name)
515 (@has_content && @has_content[name]) || false
511 (@has_content && @has_content[name]) || false
516 end
512 end
517 end
513 end
General Comments 0
You need to be logged in to leave comments. Login now