Mercurial > hg > soundsoftware-site
comparison app/helpers/application_helper.rb @ 1295:622f24f53b42 redmine-2.3
Update to Redmine SVN revision 11972 on 2.3-stable branch
author | Chris Cannam |
---|---|
date | Fri, 14 Jun 2013 09:02:21 +0100 |
parents | 3e4c3460b6ca |
children | 4f746d8966dd |
comparison
equal
deleted
inserted
replaced
1294:3e4c3460b6ca | 1295:622f24f53b42 |
---|---|
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 |
88 # Options: | 89 # Options: |
89 # * :text - Link text (default to attachment filename) | 90 # * :text - Link text (default to attachment filename) |
90 # * :download - Force download (default: false) | 91 # * :download - Force download (default: false) |
91 def link_to_attachment(attachment, options={}) | 92 def link_to_attachment(attachment, options={}) |
92 text = options.delete(:text) || attachment.filename | 93 text = options.delete(:text) || attachment.filename |
93 action = options.delete(:download) ? 'download' : 'show' | 94 route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path |
94 opt_only_path = {} | 95 html_options = options.slice!(:only_path) |
95 opt_only_path[:only_path] = (options[:only_path] == false ? false : true) | 96 url = send(route_method, attachment, attachment.filename, options) |
96 options.delete(:only_path) | 97 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 | 98 end |
102 | 99 |
103 # Generates a link to a SCM revision | 100 # Generates a link to a SCM revision |
104 # Options: | 101 # Options: |
105 # * :text - Link text (default to the formatted revision) | 102 # * :text - Link text (default to the formatted revision) |
117 end | 114 end |
118 | 115 |
119 # Generates a link to a message | 116 # Generates a link to a message |
120 def link_to_message(message, options={}, html_options = nil) | 117 def link_to_message(message, options={}, html_options = nil) |
121 link_to( | 118 link_to( |
122 h(truncate(message.subject, :length => 60)), | 119 truncate(message.subject, :length => 60), |
123 { :controller => 'messages', :action => 'show', | 120 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), | 121 :r => (message.parent_id && message.id), |
127 :anchor => (message.parent_id ? "message-#{message.id}" : nil) | 122 :anchor => (message.parent_id ? "message-#{message.id}" : nil) |
128 }.merge(options), | 123 }.merge(options)), |
129 html_options | 124 html_options |
130 ) | 125 ) |
131 end | 126 end |
132 | 127 |
133 # Generates a link to a project if active | 128 # Generates a link to a project if active |
134 # Examples: | 129 # Examples: |
135 # | 130 # |
136 # link_to_project(project) # => link to the specified project overview | 131 # 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 | 132 # 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) | 133 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview) |
140 # | 134 # |
141 def link_to_project(project, options={}, html_options = nil) | 135 def link_to_project(project, options={}, html_options = nil) |
142 if project.archived? | 136 if project.archived? |
143 h(project) | 137 h(project.name) |
144 else | 138 elsif options.key?(:action) |
139 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) | 140 url = {:controller => 'projects', :action => 'show', :id => project}.merge(options) |
146 link_to(h(project), url, html_options) | 141 link_to project.name, url, html_options |
142 else | |
143 link_to project.name, project_path(project, options), html_options | |
144 end | |
145 end | |
146 | |
147 # Generates a link to a project settings if active | |
148 def link_to_project_settings(project, options={}, html_options=nil) | |
149 if project.active? | |
150 link_to project.name, settings_project_path(project, options), html_options | |
151 elsif project.archived? | |
152 h(project.name) | |
153 else | |
154 link_to project.name, project_path(project, options), html_options | |
147 end | 155 end |
148 end | 156 end |
149 | 157 |
150 def wiki_page_path(page, options={}) | 158 def wiki_page_path(page, options={}) |
151 url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options)) | 159 url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options)) |
152 end | 160 end |
153 | 161 |
154 def thumbnail_tag(attachment) | 162 def thumbnail_tag(attachment) |
155 link_to image_tag(url_for(:controller => 'attachments', :action => 'thumbnail', :id => attachment)), | 163 link_to image_tag(thumbnail_path(attachment)), |
156 {:controller => 'attachments', :action => 'show', :id => attachment, :filename => attachment.filename}, | 164 named_attachment_path(attachment, attachment.filename), |
157 :title => attachment.filename | 165 :title => attachment.filename |
158 end | 166 end |
159 | 167 |
160 def toggle_link(name, id, options={}) | 168 def toggle_link(name, id, options={}) |
161 onclick = "$('##{id}').toggle(); " | 169 onclick = "$('##{id}').toggle(); " |
185 ).gsub(/[\r\n]+/, "<br />").html_safe | 193 ).gsub(/[\r\n]+/, "<br />").html_safe |
186 end | 194 end |
187 | 195 |
188 def format_version_name(version) | 196 def format_version_name(version) |
189 if version.project == @project | 197 if version.project == @project |
190 h(version) | 198 h(version) |
191 else | 199 else |
192 h("#{version.project} - #{version}") | 200 h("#{version.project} - #{version}") |
193 end | 201 end |
194 end | 202 end |
195 | 203 |
306 Project.project_tree(projects, &block) | 314 Project.project_tree(projects, &block) |
307 end | 315 end |
308 | 316 |
309 def principals_check_box_tags(name, principals) | 317 def principals_check_box_tags(name, principals) |
310 s = '' | 318 s = '' |
311 principals.sort.each do |principal| | 319 principals.each do |principal| |
312 s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n" | 320 s << "<label>#{ check_box_tag name, principal.id, false, :id => nil } #{h principal}</label>\n" |
313 end | 321 end |
314 s.html_safe | 322 s.html_safe |
315 end | 323 end |
316 | 324 |
317 # Returns a string for users/groups option tags | 325 # Returns a string for users/groups option tags |
333 | 341 |
334 # Options for the new membership projects combo-box | 342 # Options for the new membership projects combo-box |
335 def options_for_membership_project_select(principal, projects) | 343 def options_for_membership_project_select(principal, projects) |
336 options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---") | 344 options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---") |
337 options << project_tree_options_for_select(projects) do |p| | 345 options << project_tree_options_for_select(projects) do |p| |
338 {:disabled => principal.projects.include?(p)} | 346 {:disabled => principal.projects.to_a.include?(p)} |
339 end | 347 end |
340 options | 348 options |
341 end | 349 end |
342 | 350 |
343 # Truncates and returns the string as a single line | 351 # Truncates and returns the string as a single line |
387 end | 395 end |
388 | 396 |
389 def to_path_param(path) | 397 def to_path_param(path) |
390 str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/") | 398 str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/") |
391 str.blank? ? nil : str | 399 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 | 400 end |
446 | 401 |
447 def reorder_links(name, url, method = :post) | 402 def reorder_links(name, url, method = :post) |
448 link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), | 403 link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), |
449 url.merge({"#{name}[move_to]" => 'highest'}), | 404 url.merge({"#{name}[move_to]" => 'highest'}), |
514 css << 'action-' + action_name | 469 css << 'action-' + action_name |
515 css.join(' ') | 470 css.join(' ') |
516 end | 471 end |
517 | 472 |
518 def accesskey(s) | 473 def accesskey(s) |
519 Redmine::AccessKeys.key_for s | 474 @used_accesskeys ||= [] |
475 key = Redmine::AccessKeys.key_for(s) | |
476 return nil if @used_accesskeys.include?(key) | |
477 @used_accesskeys << key | |
478 key | |
520 end | 479 end |
521 | 480 |
522 # Formats text according to system settings. | 481 # Formats text according to system settings. |
523 # 2 ways to call this method: | 482 # 2 ways to call this method: |
524 # * with a String: textilizable(text, options) | 483 # * with a String: textilizable(text, options) |
602 if attachments.present? | 561 if attachments.present? |
603 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| | 562 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| |
604 filename, ext, alt, alttext = $1.downcase, $2, $3, $4 | 563 filename, ext, alt, alttext = $1.downcase, $2, $3, $4 |
605 # search for the picture in attachments | 564 # search for the picture in attachments |
606 if found = Attachment.latest_attach(attachments, filename) | 565 if found = Attachment.latest_attach(attachments, filename) |
607 image_url = url_for :only_path => only_path, :controller => 'attachments', | 566 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('"', '') | 567 desc = found.description.to_s.gsub('"', '') |
610 if !desc.blank? && alttext.blank? | 568 if !desc.blank? && alttext.blank? |
611 alt = " title=\"#{desc}\" alt=\"#{desc}\"" | 569 alt = " title=\"#{desc}\" alt=\"#{desc}\"" |
612 end | 570 end |
613 "src=\"#{image_url}\"#{alt}" | 571 "src=\"#{image_url}\"#{alt}" |
632 text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m| | 590 text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m| |
633 link_project = project | 591 link_project = project |
634 esc, all, page, title = $1, $2, $3, $5 | 592 esc, all, page, title = $1, $2, $3, $5 |
635 if esc.nil? | 593 if esc.nil? |
636 if page =~ /^([^\:]+)\:(.*)$/ | 594 if page =~ /^([^\:]+)\:(.*)$/ |
637 link_project = Project.find_by_identifier($1) || Project.find_by_name($1) | 595 identifier, page = $1, $2 |
638 page = $2 | 596 link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier) |
639 title ||= $1 if page.blank? | 597 title ||= identifier if page.blank? |
640 end | 598 end |
641 | 599 |
642 if link_project && link_project.wiki | 600 if link_project && link_project.wiki |
643 # extract anchor | 601 # extract anchor |
644 anchor = nil | 602 anchor = nil |
799 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} | 757 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} |
800 else | 758 else |
801 repository = project.repository | 759 repository = project.repository |
802 end | 760 end |
803 if prefix == 'commit' | 761 if prefix == 'commit' |
804 if repository && (changeset = Changeset.visible.find(:first, :conditions => ["repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%"])) | 762 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}, | 763 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', | 764 :class => 'changeset', |
807 :title => truncate_single_line(h(changeset.comments), :length => 100) | 765 :title => truncate_single_line(changeset.comments, :length => 100) |
808 end | 766 end |
809 else | 767 else |
810 if repository && User.current.allowed_to?(:browse_repository, project) | 768 if repository && User.current.allowed_to?(:browse_repository, project) |
811 name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$} | 769 name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$} |
812 path, rev, anchor = $1, $3, $5 | 770 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, | 771 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), | 772 :path => to_path_param(path), |
815 :rev => rev, | 773 :rev => rev, |
816 :anchor => anchor}, | 774 :anchor => anchor}, |
820 repo_prefix = nil | 778 repo_prefix = nil |
821 end | 779 end |
822 when 'attachment' | 780 when 'attachment' |
823 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil) | 781 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil) |
824 if attachments && attachment = Attachment.latest_attach(attachments, name) | 782 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}, | 783 link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment') |
826 :class => 'attachment' | |
827 end | 784 end |
828 when 'project' | 785 when 'project' |
829 if p = Project.visible.find(:first, :conditions => ["identifier = :s OR LOWER(name) = :s", {:s => name.downcase}]) | 786 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') | 787 link = link_to_project(p, {:only_path => only_path}, :class => 'project') |
831 end | 788 end |
832 end | 789 end |
833 end | 790 end |
834 end | 791 end |
1077 content_tag('tr', | 1034 content_tag('tr', |
1078 (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : ''.html_safe) + | 1035 (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) + | 1036 (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) | 1037 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : ''.html_safe) |
1081 ), :class => 'progress', :style => "width: #{width};").html_safe + | 1038 ), :class => 'progress', :style => "width: #{width};").html_safe + |
1082 content_tag('p', legend, :class => 'pourcent').html_safe | 1039 content_tag('p', legend, :class => 'percent').html_safe |
1083 end | 1040 end |
1084 | 1041 |
1085 def checked_image(checked=true) | 1042 def checked_image(checked=true) |
1086 if checked | 1043 if checked |
1087 image_tag 'toggle_check.png' | 1044 image_tag 'toggle_check.png' |
1121 | 1078 |
1122 tags = javascript_tag( | 1079 tags = javascript_tag( |
1123 "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " + | 1080 "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " + |
1124 "showOn: 'button', buttonImageOnly: true, buttonImage: '" + | 1081 "showOn: 'button', buttonImageOnly: true, buttonImage: '" + |
1125 path_to_image('/images/calendar.png') + | 1082 path_to_image('/images/calendar.png') + |
1126 "', showButtonPanel: true};") | 1083 "', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true};") |
1127 jquery_locale = l('jquery.locale', :default => current_language.to_s) | 1084 jquery_locale = l('jquery.locale', :default => current_language.to_s) |
1128 unless jquery_locale == 'en' | 1085 unless jquery_locale == 'en' |
1129 tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js") | 1086 tags << javascript_include_tag("i18n/jquery.ui.datepicker-#{jquery_locale}.js") |
1130 end | 1087 end |
1131 tags | 1088 tags |
1225 end | 1182 end |
1226 end | 1183 end |
1227 | 1184 |
1228 def sanitize_anchor_name(anchor) | 1185 def sanitize_anchor_name(anchor) |
1229 if ''.respond_to?(:encoding) || RUBY_PLATFORM == 'java' | 1186 if ''.respond_to?(:encoding) || RUBY_PLATFORM == 'java' |
1230 anchor.gsub(%r{[^\p{Word}\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') | 1187 anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-') |
1231 else | 1188 else |
1232 # TODO: remove when ruby1.8 is no longer supported | 1189 # TODO: remove when ruby1.8 is no longer supported |
1233 anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') | 1190 anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-') |
1234 end | 1191 end |
1235 end | 1192 end |
1236 | 1193 |
1237 # Returns the javascript tags that are included in the html layout head | 1194 # Returns the javascript tags that are included in the html layout head |
1238 def javascript_heads | 1195 def javascript_heads |
1239 tags = javascript_include_tag('jquery-1.7.2-ui-1.8.21-ujs-2.0.3', 'application') | 1196 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' | 1197 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)}'); });") | 1198 tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });") |
1242 end | 1199 end |
1243 tags | 1200 tags |
1244 end | 1201 end |