Mercurial > hg > soundsoftware-site
comparison app/helpers/application_helper.rb @ 1464:261b3d9a4903 redmine-2.4
Update to Redmine 2.4 branch rev 12663
author | Chris Cannam |
---|---|
date | Tue, 14 Jan 2014 14:37:42 +0000 |
parents | 3e4c3460b6ca |
children | 51364c0cd58f e248c7af89ec |
comparison
equal
deleted
inserted
replaced
1296:038ba2d95de8 | 1464:261b3d9a4903 |
---|---|
1 # encoding: utf-8 | 1 # encoding: utf-8 |
2 # | 2 # |
3 # Redmine - project management software | 3 # Redmine - project management software |
4 # Copyright (C) 2006-2012 Jean-Philippe Lang | 4 # Copyright (C) 2006-2013 Jean-Philippe Lang |
5 # | 5 # |
6 # This program is free software; you can redistribute it and/or | 6 # This program is free software; you can redistribute it and/or |
7 # modify it under the terms of the GNU General Public License | 7 # modify it under the terms of the GNU General Public License |
8 # as published by the Free Software Foundation; either version 2 | 8 # as published by the Free Software Foundation; either version 2 |
9 # of the License, or (at your option) any later version. | 9 # of the License, or (at your option) any later version. |
22 | 22 |
23 module ApplicationHelper | 23 module ApplicationHelper |
24 include Redmine::WikiFormatting::Macros::Definitions | 24 include Redmine::WikiFormatting::Macros::Definitions |
25 include Redmine::I18n | 25 include Redmine::I18n |
26 include GravatarHelper::PublicMethods | 26 include GravatarHelper::PublicMethods |
27 include Redmine::Pagination::Helper | |
27 | 28 |
28 extend Forwardable | 29 extend Forwardable |
29 def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter | 30 def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter |
30 | 31 |
31 # Return true if user is authorized for controller/action, otherwise false | 32 # Return true if user is authorized for controller/action, otherwise false |
76 subject = issue.subject | 77 subject = issue.subject |
77 if options[:truncate] | 78 if options[:truncate] |
78 subject = truncate(subject, :length => options[:truncate]) | 79 subject = truncate(subject, :length => options[:truncate]) |
79 end | 80 end |
80 end | 81 end |
81 s = link_to text, issue_path(issue), :class => issue.css_classes, :title => title | 82 only_path = options[:only_path].nil? ? true : options[:only_path] |
83 s = link_to text, issue_path(issue, :only_path => only_path), :class => issue.css_classes, :title => title | |
82 s << h(": #{subject}") if subject | 84 s << h(": #{subject}") if subject |
83 s = h("#{issue.project} - ") + s if options[:project] | 85 s = h("#{issue.project} - ") + s if options[:project] |
84 s | 86 s |
85 end | 87 end |
86 | 88 |
88 # Options: | 90 # Options: |
89 # * :text - Link text (default to attachment filename) | 91 # * :text - Link text (default to attachment filename) |
90 # * :download - Force download (default: false) | 92 # * :download - Force download (default: false) |
91 def link_to_attachment(attachment, options={}) | 93 def link_to_attachment(attachment, options={}) |
92 text = options.delete(:text) || attachment.filename | 94 text = options.delete(:text) || attachment.filename |
93 action = options.delete(:download) ? 'download' : 'show' | 95 route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path |
94 opt_only_path = {} | 96 html_options = options.slice!(:only_path) |
95 opt_only_path[:only_path] = (options[:only_path] == false ? false : true) | 97 url = send(route_method, attachment, attachment.filename, options) |
96 options.delete(:only_path) | 98 link_to text, url, html_options |
97 link_to(h(text), | |
98 {:controller => 'attachments', :action => action, | |
99 :id => attachment, :filename => attachment.filename}.merge(opt_only_path), | |
100 options) | |
101 end | 99 end |
102 | 100 |
103 # Generates a link to a SCM revision | 101 # Generates a link to a SCM revision |
104 # Options: | 102 # Options: |
105 # * :text - Link text (default to the formatted revision) | 103 # * :text - Link text (default to the formatted revision) |
117 end | 115 end |
118 | 116 |
119 # Generates a link to a message | 117 # Generates a link to a message |
120 def link_to_message(message, options={}, html_options = nil) | 118 def link_to_message(message, options={}, html_options = nil) |
121 link_to( | 119 link_to( |
122 h(truncate(message.subject, :length => 60)), | 120 truncate(message.subject, :length => 60), |
123 { :controller => 'messages', :action => 'show', | 121 board_message_path(message.board_id, message.parent_id || message.id, { |
124 :board_id => message.board_id, | |
125 :id => (message.parent_id || message.id), | |
126 :r => (message.parent_id && message.id), | 122 :r => (message.parent_id && message.id), |
127 :anchor => (message.parent_id ? "message-#{message.id}" : nil) | 123 :anchor => (message.parent_id ? "message-#{message.id}" : nil) |
128 }.merge(options), | 124 }.merge(options)), |
129 html_options | 125 html_options |
130 ) | 126 ) |
131 end | 127 end |
132 | 128 |
133 # Generates a link to a project if active | 129 # Generates a link to a project if active |
134 # Examples: | 130 # Examples: |
135 # | 131 # |
136 # link_to_project(project) # => link to the specified project overview | 132 # link_to_project(project) # => link to the specified project overview |
137 # link_to_project(project, :action=>'settings') # => link to project settings | |
138 # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options | 133 # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options |
139 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview) | 134 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview) |
140 # | 135 # |
141 def link_to_project(project, options={}, html_options = nil) | 136 def link_to_project(project, options={}, html_options = nil) |
142 if project.archived? | 137 if project.archived? |
143 h(project) | 138 h(project.name) |
144 else | 139 elsif options.key?(:action) |
140 ActiveSupport::Deprecation.warn "#link_to_project with :action option is deprecated and will be removed in Redmine 3.0." | |
145 url = {:controller => 'projects', :action => 'show', :id => project}.merge(options) | 141 url = {:controller => 'projects', :action => 'show', :id => project}.merge(options) |
146 link_to(h(project), url, html_options) | 142 link_to project.name, url, html_options |
143 else | |
144 link_to project.name, project_path(project, options), html_options | |
145 end | |
146 end | |
147 | |
148 # Generates a link to a project settings if active | |
149 def link_to_project_settings(project, options={}, html_options=nil) | |
150 if project.active? | |
151 link_to project.name, settings_project_path(project, options), html_options | |
152 elsif project.archived? | |
153 h(project.name) | |
154 else | |
155 link_to project.name, project_path(project, options), html_options | |
147 end | 156 end |
148 end | 157 end |
149 | 158 |
150 def wiki_page_path(page, options={}) | 159 def wiki_page_path(page, options={}) |
151 url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options)) | 160 url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options)) |
152 end | 161 end |
153 | 162 |
154 def thumbnail_tag(attachment) | 163 def thumbnail_tag(attachment) |
155 link_to image_tag(url_for(:controller => 'attachments', :action => 'thumbnail', :id => attachment)), | 164 link_to image_tag(thumbnail_path(attachment)), |
156 {:controller => 'attachments', :action => 'show', :id => attachment, :filename => attachment.filename}, | 165 named_attachment_path(attachment, attachment.filename), |
157 :title => attachment.filename | 166 :title => attachment.filename |
158 end | 167 end |
159 | 168 |
160 def toggle_link(name, id, options={}) | 169 def toggle_link(name, id, options={}) |
161 onclick = "$('##{id}').toggle(); " | 170 onclick = "$('##{id}').toggle(); " |
185 ).gsub(/[\r\n]+/, "<br />").html_safe | 194 ).gsub(/[\r\n]+/, "<br />").html_safe |
186 end | 195 end |
187 | 196 |
188 def format_version_name(version) | 197 def format_version_name(version) |
189 if version.project == @project | 198 if version.project == @project |
190 h(version) | 199 h(version) |
191 else | 200 else |
192 h("#{version.project} - #{version}") | 201 h("#{version.project} - #{version}") |
193 end | 202 end |
194 end | 203 end |
195 | 204 |
306 Project.project_tree(projects, &block) | 315 Project.project_tree(projects, &block) |
307 end | 316 end |
308 | 317 |
309 def principals_check_box_tags(name, principals) | 318 def principals_check_box_tags(name, principals) |
310 s = '' | 319 s = '' |
311 principals.sort.each do |principal| | 320 principals.each do |principal| |
312 s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n" | 321 s << "<label>#{ check_box_tag name, principal.id, false, :id => nil } #{h principal}</label>\n" |
313 end | 322 end |
314 s.html_safe | 323 s.html_safe |
315 end | 324 end |
316 | 325 |
317 # Returns a string for users/groups option tags | 326 # Returns a string for users/groups option tags |
320 if collection.include?(User.current) | 329 if collection.include?(User.current) |
321 s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id) | 330 s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id) |
322 end | 331 end |
323 groups = '' | 332 groups = '' |
324 collection.sort.each do |element| | 333 collection.sort.each do |element| |
325 selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) | 334 selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) || element.id.to_s == selected |
326 (element.is_a?(Group) ? groups : s) << %(<option value="#{element.id}"#{selected_attribute}>#{h element.name}</option>) | 335 (element.is_a?(Group) ? groups : s) << %(<option value="#{element.id}"#{selected_attribute}>#{h element.name}</option>) |
327 end | 336 end |
328 unless groups.empty? | 337 unless groups.empty? |
329 s << %(<optgroup label="#{h(l(:label_group_plural))}">#{groups}</optgroup>) | 338 s << %(<optgroup label="#{h(l(:label_group_plural))}">#{groups}</optgroup>) |
330 end | 339 end |
333 | 342 |
334 # Options for the new membership projects combo-box | 343 # Options for the new membership projects combo-box |
335 def options_for_membership_project_select(principal, projects) | 344 def options_for_membership_project_select(principal, projects) |
336 options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---") | 345 options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---") |
337 options << project_tree_options_for_select(projects) do |p| | 346 options << project_tree_options_for_select(projects) do |p| |
338 {:disabled => principal.projects.include?(p)} | 347 {:disabled => principal.projects.to_a.include?(p)} |
339 end | 348 end |
340 options | 349 options |
350 end | |
351 | |
352 def option_tag(name, text, value, selected=nil, options={}) | |
353 content_tag 'option', value, options.merge(:value => value, :selected => (value == selected)) | |
341 end | 354 end |
342 | 355 |
343 # Truncates and returns the string as a single line | 356 # Truncates and returns the string as a single line |
344 def truncate_single_line(string, *args) | 357 def truncate_single_line(string, *args) |
345 truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ') | 358 truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ') |
370 def time_tag(time) | 383 def time_tag(time) |
371 text = distance_of_time_in_words(Time.now, time) | 384 text = distance_of_time_in_words(Time.now, time) |
372 if @project | 385 if @project |
373 link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => User.current.time_to_date(time)}, :title => format_time(time)) | 386 link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => User.current.time_to_date(time)}, :title => format_time(time)) |
374 else | 387 else |
375 content_tag('acronym', text, :title => format_time(time)) | 388 content_tag('abbr', text, :title => format_time(time)) |
376 end | 389 end |
377 end | 390 end |
378 | 391 |
379 def syntax_highlight_lines(name, content) | 392 def syntax_highlight_lines(name, content) |
380 lines = [] | 393 lines = [] |
387 end | 400 end |
388 | 401 |
389 def to_path_param(path) | 402 def to_path_param(path) |
390 str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/") | 403 str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/") |
391 str.blank? ? nil : str | 404 str.blank? ? nil : str |
392 end | |
393 | |
394 def pagination_links_full(paginator, count=nil, options={}) | |
395 page_param = options.delete(:page_param) || :page | |
396 per_page_links = options.delete(:per_page_links) | |
397 url_param = params.dup | |
398 | |
399 html = '' | |
400 if paginator.current.previous | |
401 # \xc2\xab(utf-8) = « | |
402 html << link_to_content_update( | |
403 "\xc2\xab " + l(:label_previous), | |
404 url_param.merge(page_param => paginator.current.previous)) + ' ' | |
405 end | |
406 | |
407 html << (pagination_links_each(paginator, options) do |n| | |
408 link_to_content_update(n.to_s, url_param.merge(page_param => n)) | |
409 end || '') | |
410 | |
411 if paginator.current.next | |
412 # \xc2\xbb(utf-8) = » | |
413 html << ' ' + link_to_content_update( | |
414 (l(:label_next) + " \xc2\xbb"), | |
415 url_param.merge(page_param => paginator.current.next)) | |
416 end | |
417 | |
418 unless count.nil? | |
419 html << " (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})" | |
420 if per_page_links != false && links = per_page_links(paginator.items_per_page, count) | |
421 html << " | #{links}" | |
422 end | |
423 end | |
424 | |
425 html.html_safe | |
426 end | |
427 | |
428 def per_page_links(selected=nil, item_count=nil) | |
429 values = Setting.per_page_options_array | |
430 if item_count && values.any? | |
431 if item_count > values.first | |
432 max = values.detect {|value| value >= item_count} || item_count | |
433 else | |
434 max = item_count | |
435 end | |
436 values = values.select {|value| value <= max || value == selected} | |
437 end | |
438 if values.empty? || (values.size == 1 && values.first == selected) | |
439 return nil | |
440 end | |
441 links = values.collect do |n| | |
442 n == selected ? n : link_to_content_update(n, params.merge(:per_page => n)) | |
443 end | |
444 l(:label_display_per_page, links.join(', ')) | |
445 end | 405 end |
446 | 406 |
447 def reorder_links(name, url, method = :post) | 407 def reorder_links(name, url, method = :post) |
448 link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), | 408 link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), |
449 url.merge({"#{name}[move_to]" => 'highest'}), | 409 url.merge({"#{name}[move_to]" => 'highest'}), |
488 b << h(@project) | 448 b << h(@project) |
489 b.join(" \xc2\xbb ").html_safe | 449 b.join(" \xc2\xbb ").html_safe |
490 end | 450 end |
491 end | 451 end |
492 | 452 |
453 # Returns a h2 tag and sets the html title with the given arguments | |
454 def title(*args) | |
455 strings = args.map do |arg| | |
456 if arg.is_a?(Array) && arg.size >= 2 | |
457 link_to(*arg) | |
458 else | |
459 h(arg.to_s) | |
460 end | |
461 end | |
462 html_title args.reverse.map {|s| (s.is_a?(Array) ? s.first : s).to_s} | |
463 content_tag('h2', strings.join(' » ').html_safe) | |
464 end | |
465 | |
466 # Sets the html title | |
467 # Returns the html title when called without arguments | |
468 # Current project name and app_title and automatically appended | |
469 # Exemples: | |
470 # html_title 'Foo', 'Bar' | |
471 # html_title # => 'Foo - Bar - My Project - Redmine' | |
493 def html_title(*args) | 472 def html_title(*args) |
494 if args.empty? | 473 if args.empty? |
495 title = @html_title || [] | 474 title = @html_title || [] |
496 title << @project.name if @project | 475 title << @project.name if @project |
497 title << Setting.app_title unless Setting.app_title == title.last | 476 title << Setting.app_title unless Setting.app_title == title.last |
498 title.select {|t| !t.blank? }.join(' - ') | 477 title.reject(&:blank?).join(' - ') |
499 else | 478 else |
500 @html_title ||= [] | 479 @html_title ||= [] |
501 @html_title += args | 480 @html_title += args |
502 end | 481 end |
503 end | 482 end |
508 css = [] | 487 css = [] |
509 if theme = Redmine::Themes.theme(Setting.ui_theme) | 488 if theme = Redmine::Themes.theme(Setting.ui_theme) |
510 css << 'theme-' + theme.name | 489 css << 'theme-' + theme.name |
511 end | 490 end |
512 | 491 |
492 css << 'project-' + @project.identifier if @project && @project.identifier.present? | |
513 css << 'controller-' + controller_name | 493 css << 'controller-' + controller_name |
514 css << 'action-' + action_name | 494 css << 'action-' + action_name |
515 css.join(' ') | 495 css.join(' ') |
516 end | 496 end |
517 | 497 |
518 def accesskey(s) | 498 def accesskey(s) |
519 Redmine::AccessKeys.key_for s | 499 @used_accesskeys ||= [] |
500 key = Redmine::AccessKeys.key_for(s) | |
501 return nil if @used_accesskeys.include?(key) | |
502 @used_accesskeys << key | |
503 key | |
520 end | 504 end |
521 | 505 |
522 # Formats text according to system settings. | 506 # Formats text according to system settings. |
523 # 2 ways to call this method: | 507 # 2 ways to call this method: |
524 # * with a String: textilizable(text, options) | 508 # * with a String: textilizable(text, options) |
602 if attachments.present? | 586 if attachments.present? |
603 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| | 587 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| |
604 filename, ext, alt, alttext = $1.downcase, $2, $3, $4 | 588 filename, ext, alt, alttext = $1.downcase, $2, $3, $4 |
605 # search for the picture in attachments | 589 # search for the picture in attachments |
606 if found = Attachment.latest_attach(attachments, filename) | 590 if found = Attachment.latest_attach(attachments, filename) |
607 image_url = url_for :only_path => only_path, :controller => 'attachments', | 591 image_url = download_named_attachment_path(found, found.filename, :only_path => only_path) |
608 :action => 'download', :id => found | |
609 desc = found.description.to_s.gsub('"', '') | 592 desc = found.description.to_s.gsub('"', '') |
610 if !desc.blank? && alttext.blank? | 593 if !desc.blank? && alttext.blank? |
611 alt = " title=\"#{desc}\" alt=\"#{desc}\"" | 594 alt = " title=\"#{desc}\" alt=\"#{desc}\"" |
612 end | 595 end |
613 "src=\"#{image_url}\"#{alt}" | 596 "src=\"#{image_url}\"#{alt}" |
632 text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m| | 615 text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m| |
633 link_project = project | 616 link_project = project |
634 esc, all, page, title = $1, $2, $3, $5 | 617 esc, all, page, title = $1, $2, $3, $5 |
635 if esc.nil? | 618 if esc.nil? |
636 if page =~ /^([^\:]+)\:(.*)$/ | 619 if page =~ /^([^\:]+)\:(.*)$/ |
637 link_project = Project.find_by_identifier($1) || Project.find_by_name($1) | 620 identifier, page = $1, $2 |
638 page = $2 | 621 link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier) |
639 title ||= $1 if page.blank? | 622 title ||= identifier if page.blank? |
640 end | 623 end |
641 | 624 |
642 if link_project && link_project.wiki | 625 if link_project && link_project.wiki |
643 # extract anchor | 626 # extract anchor |
644 anchor = nil | 627 anchor = nil |
655 when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '') | 638 when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '') |
656 when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export | 639 when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export |
657 else | 640 else |
658 wiki_page_id = page.present? ? Wiki.titleize(page) : nil | 641 wiki_page_id = page.present? ? Wiki.titleize(page) : nil |
659 parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil | 642 parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil |
660 url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project, | 643 url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project, |
661 :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent) | 644 :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent) |
662 end | 645 end |
663 end | 646 end |
664 link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new'))) | 647 link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new'))) |
665 else | 648 else |
696 # source:some/file#L120 -> Link to line 120 of the file | 679 # source:some/file#L120 -> Link to line 120 of the file |
697 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52 | 680 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52 |
698 # export:some/file -> Force the download of the file | 681 # export:some/file -> Force the download of the file |
699 # Forum messages: | 682 # Forum messages: |
700 # message#1218 -> Link to message with id 1218 | 683 # message#1218 -> Link to message with id 1218 |
684 # Projects: | |
685 # project:someproject -> Link to project named "someproject" | |
686 # project#3 -> Link to project with id 3 | |
701 # | 687 # |
702 # Links can refer other objects from other projects, using project identifier: | 688 # Links can refer other objects from other projects, using project identifier: |
703 # identifier:r52 | 689 # identifier:r52 |
704 # identifier:document:"Some document" | 690 # identifier:document:"Some document" |
705 # identifier:version:1.0.0 | 691 # identifier:version:1.0.0 |
732 oid = identifier.to_i | 718 oid = identifier.to_i |
733 case prefix | 719 case prefix |
734 when nil | 720 when nil |
735 if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status) | 721 if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status) |
736 anchor = comment_id ? "note-#{comment_id}" : nil | 722 anchor = comment_id ? "note-#{comment_id}" : nil |
737 link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor}, | 723 link = link_to(h("##{oid}#{comment_suffix}"), {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor}, |
738 :class => issue.css_classes, | 724 :class => issue.css_classes, |
739 :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})") | 725 :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})") |
740 end | 726 end |
741 when 'document' | 727 when 'document' |
742 if document = Document.visible.find_by_id(oid) | 728 if document = Document.visible.find_by_id(oid) |
799 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} | 785 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} |
800 else | 786 else |
801 repository = project.repository | 787 repository = project.repository |
802 end | 788 end |
803 if prefix == 'commit' | 789 if prefix == 'commit' |
804 if repository && (changeset = Changeset.visible.find(:first, :conditions => ["repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%"])) | 790 if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first) |
805 link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier}, | 791 link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier}, |
806 :class => 'changeset', | 792 :class => 'changeset', |
807 :title => truncate_single_line(h(changeset.comments), :length => 100) | 793 :title => truncate_single_line(changeset.comments, :length => 100) |
808 end | 794 end |
809 else | 795 else |
810 if repository && User.current.allowed_to?(:browse_repository, project) | 796 if repository && User.current.allowed_to?(:browse_repository, project) |
811 name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$} | 797 name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$} |
812 path, rev, anchor = $1, $3, $5 | 798 path, rev, anchor = $1, $3, $5 |
813 link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param, | 799 link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param, |
814 :path => to_path_param(path), | 800 :path => to_path_param(path), |
815 :rev => rev, | 801 :rev => rev, |
816 :anchor => anchor}, | 802 :anchor => anchor}, |
820 repo_prefix = nil | 806 repo_prefix = nil |
821 end | 807 end |
822 when 'attachment' | 808 when 'attachment' |
823 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil) | 809 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil) |
824 if attachments && attachment = Attachment.latest_attach(attachments, name) | 810 if attachments && attachment = Attachment.latest_attach(attachments, name) |
825 link = link_to h(attachment.filename), {:only_path => only_path, :controller => 'attachments', :action => 'download', :id => attachment}, | 811 link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment') |
826 :class => 'attachment' | |
827 end | 812 end |
828 when 'project' | 813 when 'project' |
829 if p = Project.visible.find(:first, :conditions => ["identifier = :s OR LOWER(name) = :s", {:s => name.downcase}]) | 814 if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first |
830 link = link_to_project(p, {:only_path => only_path}, :class => 'project') | 815 link = link_to_project(p, {:only_path => only_path}, :class => 'project') |
831 end | 816 end |
832 end | 817 end |
833 end | 818 end |
834 end | 819 end |
845 @current_section += 1 | 830 @current_section += 1 |
846 if @current_section > 1 | 831 if @current_section > 1 |
847 content_tag('div', | 832 content_tag('div', |
848 link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)), | 833 link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)), |
849 :class => 'contextual', | 834 :class => 'contextual', |
850 :title => l(:button_edit_section)) + heading.html_safe | 835 :title => l(:button_edit_section), |
836 :id => "section-#{@current_section}") + heading.html_safe | |
851 else | 837 else |
852 heading | 838 heading |
853 end | 839 end |
854 end | 840 end |
855 end | 841 end |
1016 html << "<li>#{h error}</li>\n" | 1002 html << "<li>#{h error}</li>\n" |
1017 end | 1003 end |
1018 html << "</ul></div>\n" | 1004 html << "</ul></div>\n" |
1019 end | 1005 end |
1020 html.html_safe | 1006 html.html_safe |
1021 end | 1007 end |
1022 | 1008 |
1023 def delete_link(url, options={}) | 1009 def delete_link(url, options={}) |
1024 options = { | 1010 options = { |
1025 :method => :delete, | 1011 :method => :delete, |
1026 :data => {:confirm => l(:text_are_you_sure)}, | 1012 :data => {:confirm => l(:text_are_you_sure)}, |
1030 link_to l(:button_delete), url, options | 1016 link_to l(:button_delete), url, options |
1031 end | 1017 end |
1032 | 1018 |
1033 def preview_link(url, form, target='preview', options={}) | 1019 def preview_link(url, form, target='preview', options={}) |
1034 content_tag 'a', l(:label_preview), { | 1020 content_tag 'a', l(:label_preview), { |
1035 :href => "#", | 1021 :href => "#", |
1036 :onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|, | 1022 :onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|, |
1037 :accesskey => accesskey(:preview) | 1023 :accesskey => accesskey(:preview) |
1038 }.merge(options) | 1024 }.merge(options) |
1039 end | 1025 end |
1040 | 1026 |
1041 def link_to_function(name, function, html_options={}) | 1027 def link_to_function(name, function, html_options={}) |
1076 content_tag('table', | 1062 content_tag('table', |
1077 content_tag('tr', | 1063 content_tag('tr', |
1078 (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : ''.html_safe) + | 1064 (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : ''.html_safe) + |
1079 (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : ''.html_safe) + | 1065 (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : ''.html_safe) + |
1080 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : ''.html_safe) | 1066 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : ''.html_safe) |
1081 ), :class => 'progress', :style => "width: #{width};").html_safe + | 1067 ), :class => "progress progress-#{pcts[0]}", :style => "width: #{width};").html_safe + |
1082 content_tag('p', legend, :class => 'pourcent').html_safe | 1068 content_tag('p', legend, :class => 'percent').html_safe |
1083 end | 1069 end |
1084 | 1070 |
1085 def checked_image(checked=true) | 1071 def checked_image(checked=true) |
1086 if checked | 1072 if checked |
1087 image_tag 'toggle_check.png' | 1073 image_tag 'toggle_check.png' |
1109 javascript_tag("$(function() { $('##{field_id}').datepicker(datepickerOptions); });") | 1095 javascript_tag("$(function() { $('##{field_id}').datepicker(datepickerOptions); });") |
1110 end | 1096 end |
1111 | 1097 |
1112 def include_calendar_headers_tags | 1098 def include_calendar_headers_tags |
1113 unless @calendar_headers_tags_included | 1099 unless @calendar_headers_tags_included |
1100 tags = javascript_include_tag("datepicker") | |
1114 @calendar_headers_tags_included = true | 1101 @calendar_headers_tags_included = true |
1115 content_for :header_tags do | 1102 content_for :header_tags do |
1116 start_of_week = Setting.start_of_week | 1103 start_of_week = Setting.start_of_week |
1117 start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank? | 1104 start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank? |
1118 # Redmine uses 1..7 (monday..sunday) in settings and locales | 1105 # Redmine uses 1..7 (monday..sunday) in settings and locales |
1119 # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0 | 1106 # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0 |
1120 start_of_week = start_of_week.to_i % 7 | 1107 start_of_week = start_of_week.to_i % 7 |
1121 | 1108 tags << javascript_tag( |
1122 tags = javascript_tag( | |
1123 "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " + | 1109 "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " + |
1124 "showOn: 'button', buttonImageOnly: true, buttonImage: '" + | 1110 "showOn: 'button', buttonImageOnly: true, buttonImage: '" + |
1125 path_to_image('/images/calendar.png') + | 1111 path_to_image('/images/calendar.png') + |
1126 "', showButtonPanel: true};") | 1112 "', showButtonPanel: true, showWeek: true, showOtherMonths: true, " + |
1113 "selectOtherMonths: true, changeMonth: true, changeYear: true, " + | |
1114 "beforeShow: beforeShowDatePicker};") | |
1127 jquery_locale = l('jquery.locale', :default => current_language.to_s) | 1115 jquery_locale = l('jquery.locale', :default => current_language.to_s) |
1128 unless jquery_locale == 'en' | 1116 unless jquery_locale == 'en' |
1129 tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js") | 1117 tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js") |
1130 end | 1118 end |
1131 tags | 1119 tags |
1132 end | 1120 end |
1133 end | 1121 end |
1134 end | 1122 end |
1184 end | 1172 end |
1185 end | 1173 end |
1186 super sources, options | 1174 super sources, options |
1187 end | 1175 end |
1188 | 1176 |
1189 def content_for(name, content = nil, &block) | 1177 # TODO: remove this in 2.5.0 |
1190 @has_content ||= {} | |
1191 @has_content[name] = true | |
1192 super(name, content, &block) | |
1193 end | |
1194 | |
1195 def has_content?(name) | 1178 def has_content?(name) |
1196 (@has_content && @has_content[name]) || false | 1179 content_for?(name) |
1197 end | 1180 end |
1198 | 1181 |
1199 def sidebar_content? | 1182 def sidebar_content? |
1200 has_content?(:sidebar) || view_layouts_base_sidebar_hook_response.present? | 1183 content_for?(:sidebar) || view_layouts_base_sidebar_hook_response.present? |
1201 end | 1184 end |
1202 | 1185 |
1203 def view_layouts_base_sidebar_hook_response | 1186 def view_layouts_base_sidebar_hook_response |
1204 @view_layouts_base_sidebar_hook_response ||= call_hook(:view_layouts_base_sidebar) | 1187 @view_layouts_base_sidebar_hook_response ||= call_hook(:view_layouts_base_sidebar) |
1205 end | 1188 end |
1225 end | 1208 end |
1226 end | 1209 end |
1227 | 1210 |
1228 def sanitize_anchor_name(anchor) | 1211 def sanitize_anchor_name(anchor) |
1229 if ''.respond_to?(:encoding) || RUBY_PLATFORM == 'java' | 1212 if ''.respond_to?(:encoding) || RUBY_PLATFORM == 'java' |
1230 anchor.gsub(%r{[^\p{Word}\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') | 1213 anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-') |
1231 else | 1214 else |
1232 # TODO: remove when ruby1.8 is no longer supported | 1215 # TODO: remove when ruby1.8 is no longer supported |
1233 anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') | 1216 anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') |
1234 end | 1217 end |
1235 end | 1218 end |
1236 | 1219 |
1237 # Returns the javascript tags that are included in the html layout head | 1220 # Returns the javascript tags that are included in the html layout head |
1238 def javascript_heads | 1221 def javascript_heads |
1239 tags = javascript_include_tag('jquery-1.7.2-ui-1.8.21-ujs-2.0.3', 'application') | 1222 tags = javascript_include_tag('jquery-1.8.3-ui-1.9.2-ujs-2.0.3', 'application') |
1240 unless User.current.pref.warn_on_leaving_unsaved == '0' | 1223 unless User.current.pref.warn_on_leaving_unsaved == '0' |
1241 tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });") | 1224 tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });") |
1242 end | 1225 end |
1243 tags | 1226 tags |
1244 end | 1227 end |