Mercurial > hg > soundsoftware-site
comparison app/helpers/.svn/text-base/application_helper.rb.svn-base @ 441:cbce1fd3b1b7 redmine-1.2
Update to Redmine 1.2-stable branch (Redmine SVN rev 6000)
author | Chris Cannam |
---|---|
date | Mon, 06 Jun 2011 14:24:13 +0100 |
parents | 051f544170fe |
children | 753f1380d6bc |
comparison
equal
deleted
inserted
replaced
245:051f544170fe | 441:cbce1fd3b1b7 |
---|---|
1 # Redmine - project management software | 1 # Redmine - project management software |
2 # Copyright (C) 2006-2010 Jean-Philippe Lang | 2 # Copyright (C) 2006-2011 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. |
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 # |
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 |
107 rev = revision.respond_to?(:identifier) ? revision.identifier : revision | 107 rev = revision.respond_to?(:identifier) ? revision.identifier : revision |
108 | 108 |
109 link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => rev}, | 109 link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => rev}, |
110 :title => l(:label_revision_id, format_revision(revision))) | 110 :title => l(:label_revision_id, format_revision(revision))) |
111 end | 111 end |
112 | 112 |
113 # Generates a link to a message | 113 # Generates a link to a message |
114 def link_to_message(message, options={}, html_options = nil) | 114 def link_to_message(message, options={}, html_options = nil) |
115 link_to( | 115 link_to( |
116 h(truncate(message.subject, :length => 60)), | 116 h(truncate(message.subject, :length => 60)), |
117 { :controller => 'messages', :action => 'show', | 117 { :controller => 'messages', :action => 'show', |
124 ) | 124 ) |
125 end | 125 end |
126 | 126 |
127 # Generates a link to a project if active | 127 # Generates a link to a project if active |
128 # Examples: | 128 # Examples: |
129 # | 129 # |
130 # link_to_project(project) # => link to the specified project overview | 130 # link_to_project(project) # => link to the specified project overview |
131 # link_to_project(project, :action=>'settings') # => link to project settings | 131 # link_to_project(project, :action=>'settings') # => link to project settings |
132 # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options | 132 # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options |
133 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview) | 133 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview) |
134 # | 134 # |
158 | 158 |
159 def prompt_to_remote(name, text, param, url, html_options = {}) | 159 def prompt_to_remote(name, text, param, url, html_options = {}) |
160 html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;" | 160 html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;" |
161 link_to name, {}, html_options | 161 link_to name, {}, html_options |
162 end | 162 end |
163 | 163 |
164 def format_activity_title(text) | 164 def format_activity_title(text) |
165 h(truncate_single_line(text, :length => 100)) | 165 h(truncate_single_line(text, :length => 100)) |
166 end | 166 end |
167 | 167 |
168 def format_activity_day(date) | 168 def format_activity_day(date) |
169 date == Date.today ? l(:label_today).titleize : format_date(date) | 169 date == Date.today ? l(:label_today).titleize : format_date(date) |
170 end | 170 end |
171 | 171 |
172 def format_activity_description(text) | 172 def format_activity_description(text) |
173 h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />") | 173 h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')).gsub(/[\r\n]+/, "<br />") |
174 end | 174 end |
175 | 175 |
176 def format_version_name(version) | 176 def format_version_name(version) |
178 h(version) | 178 h(version) |
179 else | 179 else |
180 h("#{version.project} - #{version}") | 180 h("#{version.project} - #{version}") |
181 end | 181 end |
182 end | 182 end |
183 | 183 |
184 def due_date_distance_in_words(date) | 184 def due_date_distance_in_words(date) |
185 if date | 185 if date |
186 l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date)) | 186 l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date)) |
187 end | 187 end |
188 end | 188 end |
189 | 189 |
190 def render_page_hierarchy(pages, node=nil) | 190 def render_page_hierarchy(pages, node=nil, options={}) |
191 content = '' | 191 content = '' |
192 if pages[node] | 192 if pages[node] |
193 content << "<ul class=\"pages-hierarchy\">\n" | 193 content << "<ul class=\"pages-hierarchy\">\n" |
194 pages[node].each do |page| | 194 pages[node].each do |page| |
195 content << "<li>" | 195 content << "<li>" |
196 content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}, | 196 content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}, |
197 :title => (page.respond_to?(:updated_on) ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil)) | 197 :title => (options[:timestamp] && page.updated_on ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil)) |
198 content << "\n" + render_page_hierarchy(pages, page.id) if pages[page.id] | 198 content << "\n" + render_page_hierarchy(pages, page.id, options) if pages[page.id] |
199 content << "</li>\n" | 199 content << "</li>\n" |
200 end | 200 end |
201 content << "</ul>\n" | 201 content << "</ul>\n" |
202 end | 202 end |
203 content | 203 content |
204 end | 204 end |
205 | 205 |
206 # Renders flash messages | 206 # Renders flash messages |
207 def render_flash_messages | 207 def render_flash_messages |
208 s = '' | 208 s = '' |
209 flash.each do |k,v| | 209 flash.each do |k,v| |
210 s << content_tag('div', v, :class => "flash #{k}") | 210 s << content_tag('div', v, :class => "flash #{k}") |
211 end | 211 end |
212 s | 212 s |
213 end | 213 end |
214 | 214 |
215 # Renders tabs and their content | 215 # Renders tabs and their content |
216 def render_tabs(tabs) | 216 def render_tabs(tabs) |
217 if tabs.any? | 217 if tabs.any? |
218 render :partial => 'common/tabs', :locals => {:tabs => tabs} | 218 render :partial => 'common/tabs', :locals => {:tabs => tabs} |
219 else | 219 else |
220 content_tag 'p', l(:label_no_data), :class => "nodata" | 220 content_tag 'p', l(:label_no_data), :class => "nodata" |
221 end | 221 end |
222 end | 222 end |
223 | 223 |
224 # Renders the project quick-jump box | 224 # Renders the project quick-jump box |
225 def render_project_jump_box | 225 def render_project_jump_box |
226 # Retrieve them now to avoid a COUNT query | 226 return unless User.current.logged? |
227 projects = User.current.projects.all | 227 projects = User.current.memberships.collect(&:project).compact.uniq |
228 if projects.any? | 228 if projects.any? |
229 s = '<select onchange="if (this.value != \'\') { window.location = this.value; }">' + | 229 s = '<select onchange="if (this.value != \'\') { window.location = this.value; }">' + |
230 "<option value=''>#{ l(:label_jump_to_a_project) }</option>" + | 230 "<option value=''>#{ l(:label_jump_to_a_project) }</option>" + |
231 '<option value="" disabled="disabled">---</option>' | 231 '<option value="" disabled="disabled">---</option>' |
232 s << project_tree_options_for_select(projects, :selected => @project) do |p| | 232 s << project_tree_options_for_select(projects, :selected => @project) do |p| |
234 end | 234 end |
235 s << '</select>' | 235 s << '</select>' |
236 s | 236 s |
237 end | 237 end |
238 end | 238 end |
239 | 239 |
240 def project_tree_options_for_select(projects, options = {}) | 240 def project_tree_options_for_select(projects, options = {}) |
241 s = '' | 241 s = '' |
242 project_tree(projects) do |project, level| | 242 project_tree(projects) do |project, level| |
243 name_prefix = (level > 0 ? (' ' * 2 * level + '» ') : '') | 243 name_prefix = (level > 0 ? (' ' * 2 * level + '» ') : '') |
244 tag_options = {:value => project.id} | 244 tag_options = {:value => project.id} |
250 tag_options.merge!(yield(project)) if block_given? | 250 tag_options.merge!(yield(project)) if block_given? |
251 s << content_tag('option', name_prefix + h(project), tag_options) | 251 s << content_tag('option', name_prefix + h(project), tag_options) |
252 end | 252 end |
253 s | 253 s |
254 end | 254 end |
255 | 255 |
256 # Yields the given block for each project with its level in the tree | 256 # Yields the given block for each project with its level in the tree |
257 # | 257 # |
258 # Wrapper for Project#project_tree | 258 # Wrapper for Project#project_tree |
259 def project_tree(projects, &block) | 259 def project_tree(projects, &block) |
260 Project.project_tree(projects, &block) | 260 Project.project_tree(projects, &block) |
261 end | 261 end |
262 | 262 |
263 def project_nested_ul(projects, &block) | 263 def project_nested_ul(projects, &block) |
264 s = '' | 264 s = '' |
265 if projects.any? | 265 if projects.any? |
266 ancestors = [] | 266 ancestors = [] |
267 projects.sort_by(&:lft).each do |project| | 267 projects.sort_by(&:lft).each do |project| |
268 if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) | 268 if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) |
269 s << "<ul>\n" | 269 s << "<ul>\n" |
270 else | 270 else |
271 ancestors.pop | 271 ancestors.pop |
272 s << "</li>" | 272 s << "</li>" |
273 while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) | 273 while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) |
274 ancestors.pop | 274 ancestors.pop |
275 s << "</ul></li>\n" | 275 s << "</ul></li>\n" |
276 end | 276 end |
277 end | 277 end |
278 s << "<li>" | 278 s << "<li>" |
281 end | 281 end |
282 s << ("</li></ul>\n" * ancestors.size) | 282 s << ("</li></ul>\n" * ancestors.size) |
283 end | 283 end |
284 s | 284 s |
285 end | 285 end |
286 | 286 |
287 def principals_check_box_tags(name, principals) | 287 def principals_check_box_tags(name, principals) |
288 s = '' | 288 s = '' |
289 principals.sort.each do |principal| | 289 principals.sort.each do |principal| |
290 s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n" | 290 s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n" |
291 end | 291 end |
292 s | 292 s |
293 end | 293 end |
294 | 294 |
295 # Truncates and returns the string as a single line | 295 # Truncates and returns the string as a single line |
296 def truncate_single_line(string, *args) | 296 def truncate_single_line(string, *args) |
297 truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ') | 297 truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ') |
298 end | 298 end |
299 | 299 |
300 # Truncates at line break after 250 characters or options[:length] | 300 # Truncates at line break after 250 characters or options[:length] |
301 def truncate_lines(string, options={}) | 301 def truncate_lines(string, options={}) |
302 length = options[:length] || 250 | 302 length = options[:length] || 250 |
303 if string.to_s =~ /\A(.{#{length}}.*?)$/m | 303 if string.to_s =~ /\A(.{#{length}}.*?)$/m |
304 "#{$1}..." | 304 "#{$1}..." |
312 end | 312 end |
313 | 313 |
314 def authoring(created, author, options={}) | 314 def authoring(created, author, options={}) |
315 l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)) | 315 l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)) |
316 end | 316 end |
317 | 317 |
318 def time_tag(time) | 318 def time_tag(time) |
319 text = distance_of_time_in_words(Time.now, time) | 319 text = distance_of_time_in_words(Time.now, time) |
320 if @project | 320 if @project |
321 link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => time.to_date}, :title => format_time(time)) | 321 link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => time.to_date}, :title => format_time(time)) |
322 else | 322 else |
334 | 334 |
335 def pagination_links_full(paginator, count=nil, options={}) | 335 def pagination_links_full(paginator, count=nil, options={}) |
336 page_param = options.delete(:page_param) || :page | 336 page_param = options.delete(:page_param) || :page |
337 per_page_links = options.delete(:per_page_links) | 337 per_page_links = options.delete(:per_page_links) |
338 url_param = params.dup | 338 url_param = params.dup |
339 # don't reuse query params if filters are present | |
340 url_param.merge!(:fields => nil, :values => nil, :operators => nil) if url_param.delete(:set_filter) | |
341 | 339 |
342 html = '' | 340 html = '' |
343 if paginator.current.previous | 341 if paginator.current.previous |
344 html << link_to_remote_content_update('« ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' ' | 342 html << link_to_content_update('« ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' ' |
345 end | 343 end |
346 | 344 |
347 html << (pagination_links_each(paginator, options) do |n| | 345 html << (pagination_links_each(paginator, options) do |n| |
348 link_to_remote_content_update(n.to_s, url_param.merge(page_param => n)) | 346 link_to_content_update(n.to_s, url_param.merge(page_param => n)) |
349 end || '') | 347 end || '') |
350 | 348 |
351 if paginator.current.next | 349 if paginator.current.next |
352 html << ' ' + link_to_remote_content_update((l(:label_next) + ' »'), url_param.merge(page_param => paginator.current.next)) | 350 html << ' ' + link_to_content_update((l(:label_next) + ' »'), url_param.merge(page_param => paginator.current.next)) |
353 end | 351 end |
354 | 352 |
355 unless count.nil? | 353 unless count.nil? |
356 html << " (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})" | 354 html << " (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})" |
357 if per_page_links != false && links = per_page_links(paginator.items_per_page) | 355 if per_page_links != false && links = per_page_links(paginator.items_per_page) |
359 end | 357 end |
360 end | 358 end |
361 | 359 |
362 html | 360 html |
363 end | 361 end |
364 | 362 |
365 def per_page_links(selected=nil) | 363 def per_page_links(selected=nil) |
366 url_param = params.dup | |
367 url_param.clear if url_param.has_key?(:set_filter) | |
368 | |
369 links = Setting.per_page_options_array.collect do |n| | 364 links = Setting.per_page_options_array.collect do |n| |
370 n == selected ? n : link_to_remote(n, {:update => "content", | 365 n == selected ? n : link_to_content_update(n, params.merge(:per_page => n)) |
371 :url => params.dup.merge(:per_page => n), | |
372 :method => :get}, | |
373 {:href => url_for(url_param.merge(:per_page => n))}) | |
374 end | 366 end |
375 links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil | 367 links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil |
376 end | 368 end |
377 | 369 |
378 def reorder_links(name, url) | 370 def reorder_links(name, url) |
379 link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), url.merge({"#{name}[move_to]" => 'highest'}), :method => :post, :title => l(:label_sort_highest)) + | 371 link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), url.merge({"#{name}[move_to]" => 'highest'}), :method => :post, :title => l(:label_sort_highest)) + |
380 link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), url.merge({"#{name}[move_to]" => 'higher'}), :method => :post, :title => l(:label_sort_higher)) + | 372 link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), url.merge({"#{name}[move_to]" => 'higher'}), :method => :post, :title => l(:label_sort_higher)) + |
381 link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), url.merge({"#{name}[move_to]" => 'lower'}), :method => :post, :title => l(:label_sort_lower)) + | 373 link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), url.merge({"#{name}[move_to]" => 'lower'}), :method => :post, :title => l(:label_sort_lower)) + |
382 link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), url.merge({"#{name}[move_to]" => 'lowest'}), :method => :post, :title => l(:label_sort_lowest)) | 374 link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), url.merge({"#{name}[move_to]" => 'lowest'}), :method => :post, :title => l(:label_sort_lowest)) |
384 | 376 |
385 def breadcrumb(*args) | 377 def breadcrumb(*args) |
386 elements = args.flatten | 378 elements = args.flatten |
387 elements.any? ? content_tag('p', args.join(' » ') + ' » ', :class => 'breadcrumb') : nil | 379 elements.any? ? content_tag('p', args.join(' » ') + ' » ', :class => 'breadcrumb') : nil |
388 end | 380 end |
389 | 381 |
390 def other_formats_links(&block) | 382 def other_formats_links(&block) |
391 concat('<p class="other-formats">' + l(:label_export_to)) | 383 concat('<p class="other-formats">' + l(:label_export_to)) |
392 yield Redmine::Views::OtherFormatsBuilder.new(self) | 384 yield Redmine::Views::OtherFormatsBuilder.new(self) |
393 concat('</p>') | 385 concat('</p>') |
394 end | 386 end |
395 | 387 |
396 def page_header_title | 388 def page_header_title |
397 if @project.nil? || @project.new_record? | 389 if @project.nil? || @project.new_record? |
398 h(Setting.app_title) | 390 h(Setting.app_title) |
399 else | 391 else |
400 b = [] | 392 b = [] |
401 ancestors = (@project.root? ? [] : @project.ancestors.visible) | 393 ancestors = (@project.root? ? [] : @project.ancestors.visible.all) |
402 if ancestors.any? | 394 if ancestors.any? |
403 root = ancestors.shift | 395 root = ancestors.shift |
404 b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') | 396 b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') |
405 if ancestors.size > 2 | 397 if ancestors.size > 2 |
406 b << '…' | 398 b << '…' |
463 return '' if text.blank? | 455 return '' if text.blank? |
464 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) | 456 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) |
465 only_path = options.delete(:only_path) == false ? false : true | 457 only_path = options.delete(:only_path) == false ? false : true |
466 | 458 |
467 text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) } | 459 text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) } |
468 | 460 |
469 @parsed_headings = [] | 461 @parsed_headings = [] |
470 text = parse_non_pre_blocks(text) do |text| | 462 text = parse_non_pre_blocks(text) do |text| |
471 [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name| | 463 [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name| |
472 send method_name, text, project, obj, attr, only_path, options | 464 send method_name, text, project, obj, attr, only_path, options |
473 end | 465 end |
474 end | 466 end |
475 | 467 |
476 if @parsed_headings.any? | 468 if @parsed_headings.any? |
477 replace_toc(text, @parsed_headings) | 469 replace_toc(text, @parsed_headings) |
478 end | 470 end |
479 | 471 |
480 text | 472 text |
481 end | 473 end |
482 | 474 |
483 def parse_non_pre_blocks(text) | 475 def parse_non_pre_blocks(text) |
484 s = StringScanner.new(text) | 476 s = StringScanner.new(text) |
485 tags = [] | 477 tags = [] |
486 parsed = '' | 478 parsed = '' |
487 while !s.eos? | 479 while !s.eos? |
506 while tag = tags.pop | 498 while tag = tags.pop |
507 parsed << "</#{tag}>" | 499 parsed << "</#{tag}>" |
508 end | 500 end |
509 parsed | 501 parsed |
510 end | 502 end |
511 | 503 |
512 def parse_inline_attachments(text, project, obj, attr, only_path, options) | 504 def parse_inline_attachments(text, project, obj, attr, only_path, options) |
513 # when using an image link, try to use an attachment, if possible | 505 # when using an image link, try to use an attachment, if possible |
514 if options[:attachments] || (obj && obj.respond_to?(:attachments)) | 506 if options[:attachments] || (obj && obj.respond_to?(:attachments)) |
515 attachments = nil | 507 attachments = nil |
516 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| | 508 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| |
517 filename, ext, alt, alttext = $1.downcase, $2, $3, $4 | 509 filename, ext, alt, alttext = $1.downcase, $2, $3, $4 |
518 attachments ||= (options[:attachments] || obj.attachments).sort_by(&:created_on).reverse | 510 attachments ||= (options[:attachments] || obj.attachments).sort_by(&:created_on).reverse |
519 # search for the picture in attachments | 511 # search for the picture in attachments |
520 if found = attachments.detect { |att| att.filename.downcase == filename } | 512 if found = attachments.detect { |att| att.filename.downcase == filename } |
521 image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found | 513 image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found |
522 desc = found.description.to_s.gsub('"', '') | 514 desc = found.description.to_s.gsub('"', '') |
575 else | 567 else |
576 all | 568 all |
577 end | 569 end |
578 end | 570 end |
579 end | 571 end |
580 | 572 |
581 # Redmine links | 573 # Redmine links |
582 # | 574 # |
583 # Examples: | 575 # Examples: |
584 # Issues: | 576 # Issues: |
585 # #52 -> Link to issue #52 | 577 # #52 -> Link to issue #52 |
698 end | 690 end |
699 end | 691 end |
700 leading + (link || "#{project_prefix}#{prefix}#{sep}#{identifier}") | 692 leading + (link || "#{project_prefix}#{prefix}#{sep}#{identifier}") |
701 end | 693 end |
702 end | 694 end |
703 | 695 |
704 HEADING_RE = /<h(1|2|3|4)( [^>]+)?>(.+?)<\/h(1|2|3|4)>/i unless const_defined?(:HEADING_RE) | 696 HEADING_RE = /<h(1|2|3|4)( [^>]+)?>(.+?)<\/h(1|2|3|4)>/i unless const_defined?(:HEADING_RE) |
705 | 697 |
706 # Headings and TOC | 698 # Headings and TOC |
707 # Adds ids and links to headings unless options[:headings] is set to false | 699 # Adds ids and links to headings unless options[:headings] is set to false |
708 def parse_headings(text, project, obj, attr, only_path, options) | 700 def parse_headings(text, project, obj, attr, only_path, options) |
709 return if options[:headings] == false | 701 return if options[:headings] == false |
710 | 702 |
711 text.gsub!(HEADING_RE) do | 703 text.gsub!(HEADING_RE) do |
712 level, attrs, content = $1.to_i, $2, $3 | 704 level, attrs, content = $1.to_i, $2, $3 |
713 item = strip_tags(content).strip | 705 item = strip_tags(content).strip |
714 anchor = item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') | 706 anchor = item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') |
715 @parsed_headings << [level, anchor, item] | 707 @parsed_headings << [level, anchor, item] |
716 "<h#{level} #{attrs} id=\"#{anchor}\">#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">¶</a></h#{level}>" | 708 "<a name=\"#{anchor}\"></a>\n<h#{level} #{attrs}>#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">¶</a></h#{level}>" |
717 end | 709 end |
718 end | 710 end |
719 | 711 |
720 TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) | 712 TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) |
721 | 713 |
722 # Renders the TOC with given headings | 714 # Renders the TOC with given headings |
723 def replace_toc(text, headings) | 715 def replace_toc(text, headings) |
724 text.gsub!(TOC_RE) do | 716 text.gsub!(TOC_RE) do |
725 if headings.empty? | 717 if headings.empty? |
726 '' | 718 '' |
799 (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : '') + | 791 (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : '') + |
800 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : '') | 792 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : '') |
801 ), :class => 'progress', :style => "width: #{width};") + | 793 ), :class => 'progress', :style => "width: #{width};") + |
802 content_tag('p', legend, :class => 'pourcent') | 794 content_tag('p', legend, :class => 'pourcent') |
803 end | 795 end |
804 | 796 |
805 def checked_image(checked=true) | 797 def checked_image(checked=true) |
806 if checked | 798 if checked |
807 image_tag 'toggle_check.png' | 799 image_tag 'toggle_check.png' |
808 end | 800 end |
809 end | 801 end |
810 | 802 |
811 def context_menu(url) | 803 def context_menu(url) |
812 unless @context_menu_included | 804 unless @context_menu_included |
813 content_for :header_tags do | 805 content_for :header_tags do |
814 javascript_include_tag('context_menu') + | 806 javascript_include_tag('context_menu') + |
815 stylesheet_link_tag('context_menu') | 807 stylesheet_link_tag('context_menu') |
853 start_of_week = case Setting.start_of_week.to_i | 845 start_of_week = case Setting.start_of_week.to_i |
854 when 1 | 846 when 1 |
855 'Calendar._FD = 1;' # Monday | 847 'Calendar._FD = 1;' # Monday |
856 when 7 | 848 when 7 |
857 'Calendar._FD = 0;' # Sunday | 849 'Calendar._FD = 0;' # Sunday |
850 when 6 | |
851 'Calendar._FD = 6;' # Saturday | |
858 else | 852 else |
859 '' # use language | 853 '' # use language |
860 end | 854 end |
861 | 855 |
862 javascript_include_tag('calendar/calendar') + | 856 javascript_include_tag('calendar/calendar') + |
863 javascript_include_tag("calendar/lang/calendar-#{current_language.to_s.downcase}.js") + | 857 javascript_include_tag("calendar/lang/calendar-#{current_language.to_s.downcase}.js") + |
864 javascript_tag(start_of_week) + | 858 javascript_tag(start_of_week) + |
865 javascript_include_tag('calendar/calendar-setup') + | 859 javascript_include_tag('calendar/calendar-setup') + |
866 stylesheet_link_tag('calendar') | 860 stylesheet_link_tag('calendar') |
867 end | 861 end |
868 end | 862 end |
869 end | 863 end |
892 return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil | 886 return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil |
893 else | 887 else |
894 '' | 888 '' |
895 end | 889 end |
896 end | 890 end |
897 | 891 |
898 # Returns the javascript tags that are included in the html layout head | 892 # Returns the javascript tags that are included in the html layout head |
899 def javascript_heads | 893 def javascript_heads |
900 tags = javascript_include_tag(:defaults) | 894 tags = javascript_include_tag(:defaults) |
901 unless User.current.pref.warn_on_leaving_unsaved == '0' | 895 unless User.current.pref.warn_on_leaving_unsaved == '0' |
902 tags << "\n" + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });") | 896 tags << "\n" + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });") |
905 end | 899 end |
906 | 900 |
907 def favicon | 901 def favicon |
908 "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />" | 902 "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />" |
909 end | 903 end |
910 | 904 |
905 def robot_exclusion_tag | |
906 '<meta name="robots" content="noindex,follow,noarchive" />' | |
907 end | |
908 | |
911 # Returns true if arg is expected in the API response | 909 # Returns true if arg is expected in the API response |
912 def include_in_api_response?(arg) | 910 def include_in_api_response?(arg) |
913 unless @included_in_api_response | 911 unless @included_in_api_response |
914 param = params[:include] | 912 param = params[:include] |
915 @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',') | 913 @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',') |
927 nil | 925 nil |
928 else | 926 else |
929 options | 927 options |
930 end | 928 end |
931 end | 929 end |
932 | 930 |
933 private | 931 private |
934 | 932 |
935 def wiki_helper | 933 def wiki_helper |
936 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting) | 934 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting) |
937 extend helper | 935 extend helper |
938 return self | 936 return self |
939 end | 937 end |
940 | 938 |
941 def link_to_remote_content_update(text, url_params) | 939 def link_to_content_update(text, url_params = {}, html_options = {}) |
942 link_to_remote(text, | 940 link_to(text, url_params, html_options) |
943 {:url => url_params, :method => :get, :update => 'content', :complete => 'window.scrollTo(0,0)'}, | 941 end |
944 {:href => url_for(:params => url_params)} | |
945 ) | |
946 end | |
947 | |
948 end | 942 end |