comparison app/helpers/application_helper.rb @ 1517:dffacf8a6908 redmine-2.5

Update to Redmine SVN revision 13367 on 2.5-stable branch
author Chris Cannam
date Tue, 09 Sep 2014 09:29:00 +0100
parents e248c7af89ec
children a1bdbf8a87d5
comparison
equal deleted inserted replaced
1516:b450a9d58aed 1517:dffacf8a6908
70 def link_to_issue(issue, options={}) 70 def link_to_issue(issue, options={})
71 title = nil 71 title = nil
72 subject = nil 72 subject = nil
73 text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}" 73 text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}"
74 if options[:subject] == false 74 if options[:subject] == false
75 title = truncate(issue.subject, :length => 60) 75 title = issue.subject.truncate(60)
76 else 76 else
77 subject = issue.subject 77 subject = issue.subject
78 if options[:truncate] 78 if truncate_length = options[:truncate]
79 subject = truncate(subject, :length => options[:truncate]) 79 subject = subject.truncate(truncate_length)
80 end 80 end
81 end 81 end
82 only_path = options[:only_path].nil? ? true : options[:only_path] 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 83 s = link_to(text, issue_path(issue, :only_path => only_path),
84 :class => issue.css_classes, :title => title)
84 s << h(": #{subject}") if subject 85 s << h(": #{subject}") if subject
85 s = h("#{issue.project} - ") + s if options[:project] 86 s = h("#{issue.project} - ") + s if options[:project]
86 s 87 s
87 end 88 end
88 89
115 end 116 end
116 117
117 # Generates a link to a message 118 # Generates a link to a message
118 def link_to_message(message, options={}, html_options = nil) 119 def link_to_message(message, options={}, html_options = nil)
119 link_to( 120 link_to(
120 truncate(message.subject, :length => 60), 121 message.subject.truncate(60),
121 board_message_path(message.board_id, message.parent_id || message.id, { 122 board_message_path(message.board_id, message.parent_id || message.id, {
122 :r => (message.parent_id && message.id), 123 :r => (message.parent_id && message.id),
123 :anchor => (message.parent_id ? "message-#{message.id}" : nil) 124 :anchor => (message.parent_id ? "message-#{message.id}" : nil)
124 }.merge(options)), 125 }.merge(options)),
125 html_options 126 html_options
154 else 155 else
155 link_to project.name, project_path(project, options), html_options 156 link_to project.name, project_path(project, options), html_options
156 end 157 end
157 end 158 end
158 159
160 # Helper that formats object for html or text rendering
161 def format_object(object, html=true)
162 case object.class.name
163 when 'Array'
164 object.map {|o| format_object(o, html)}.join(', ').html_safe
165 when 'Time'
166 format_time(object)
167 when 'Date'
168 format_date(object)
169 when 'Fixnum'
170 object.to_s
171 when 'Float'
172 sprintf "%.2f", object
173 when 'User'
174 html ? link_to_user(object) : object.to_s
175 when 'Project'
176 html ? link_to_project(object) : object.to_s
177 when 'Version'
178 html ? link_to(object.name, version_path(object)) : object.to_s
179 when 'TrueClass'
180 l(:general_text_Yes)
181 when 'FalseClass'
182 l(:general_text_No)
183 when 'Issue'
184 object.visible? && html ? link_to_issue(object) : "##{object.id}"
185 when 'CustomValue', 'CustomFieldValue'
186 if object.custom_field
187 f = object.custom_field.format.formatted_custom_value(self, object, html)
188 if f.nil? || f.is_a?(String)
189 f
190 else
191 format_object(f, html)
192 end
193 else
194 object.value.to_s
195 end
196 else
197 html ? h(object) : object.to_s
198 end
199 end
200
159 def wiki_page_path(page, options={}) 201 def wiki_page_path(page, options={})
160 url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options)) 202 url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options))
161 end 203 end
162 204
163 def thumbnail_tag(attachment) 205 def thumbnail_tag(attachment)
180 :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" 222 :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
181 })) 223 }))
182 end 224 end
183 225
184 def format_activity_title(text) 226 def format_activity_title(text)
185 h(truncate_single_line(text, :length => 100)) 227 h(truncate_single_line_raw(text, 100))
186 end 228 end
187 229
188 def format_activity_day(date) 230 def format_activity_day(date)
189 date == User.current.today ? l(:label_today).titleize : format_date(date) 231 date == User.current.today ? l(:label_today).titleize : format_date(date)
190 end 232 end
191 233
192 def format_activity_description(text) 234 def format_activity_description(text)
193 h(truncate(text.to_s, :length => 120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...') 235 h(text.to_s.truncate(120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')
194 ).gsub(/[\r\n]+/, "<br />").html_safe 236 ).gsub(/[\r\n]+/, "<br />").html_safe
195 end 237 end
196 238
197 def format_version_name(version) 239 def format_version_name(version)
198 if version.project == @project 240 if version.project == @project
265 end 307 end
266 s.html_safe 308 s.html_safe
267 end 309 end
268 310
269 # Renders tabs and their content 311 # Renders tabs and their content
270 def render_tabs(tabs) 312 def render_tabs(tabs, selected=params[:tab])
271 if tabs.any? 313 if tabs.any?
272 render :partial => 'common/tabs', :locals => {:tabs => tabs} 314 unless tabs.detect {|tab| tab[:name] == selected}
315 selected = nil
316 end
317 selected ||= tabs.first[:name]
318 render :partial => 'common/tabs', :locals => {:tabs => tabs, :selected_tab => selected}
273 else 319 else
274 content_tag 'p', l(:label_no_data), :class => "nodata" 320 content_tag 'p', l(:label_no_data), :class => "nodata"
275 end 321 end
276 end 322 end
277 323
353 content_tag 'option', value, options.merge(:value => value, :selected => (value == selected)) 399 content_tag 'option', value, options.merge(:value => value, :selected => (value == selected))
354 end 400 end
355 401
356 # Truncates and returns the string as a single line 402 # Truncates and returns the string as a single line
357 def truncate_single_line(string, *args) 403 def truncate_single_line(string, *args)
404 ActiveSupport::Deprecation.warn(
405 "ApplicationHelper#truncate_single_line is deprecated and will be removed in Rails 4 poring")
406 # Rails 4 ActionView::Helpers::TextHelper#truncate escapes.
407 # So, result is broken.
358 truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ') 408 truncate(string.to_s, *args).gsub(%r{[\r\n]+}m, ' ')
409 end
410
411 def truncate_single_line_raw(string, length)
412 string.truncate(length).gsub(%r{[\r\n]+}m, ' ')
359 end 413 end
360 414
361 # Truncates at line break after 250 characters or options[:length] 415 # Truncates at line break after 250 characters or options[:length]
362 def truncate_lines(string, options={}) 416 def truncate_lines(string, options={})
363 length = options[:length] || 250 417 length = options[:length] || 250
706 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} 760 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
707 else 761 else
708 repository = project.repository 762 repository = project.repository
709 end 763 end
710 # project.changesets.visible raises an SQL error because of a double join on repositories 764 # project.changesets.visible raises an SQL error because of a double join on repositories
711 if repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(repository.id, identifier)) 765 if repository &&
712 link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.revision}, 766 (changeset = Changeset.visible.
713 :class => 'changeset', 767 find_by_repository_id_and_revision(repository.id, identifier))
714 :title => truncate_single_line(changeset.comments, :length => 100)) 768 link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"),
769 {:only_path => only_path, :controller => 'repositories',
770 :action => 'revision', :id => project,
771 :repository_id => repository.identifier_param,
772 :rev => changeset.revision},
773 :class => 'changeset',
774 :title => truncate_single_line_raw(changeset.comments, 100))
715 end 775 end
716 end 776 end
717 elsif sep == '#' 777 elsif sep == '#'
718 oid = identifier.to_i 778 oid = identifier.to_i
719 case prefix 779 case prefix
720 when nil 780 when nil
721 if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status) 781 if oid.to_s == identifier &&
782 issue = Issue.visible.includes(:status).find_by_id(oid)
722 anchor = comment_id ? "note-#{comment_id}" : nil 783 anchor = comment_id ? "note-#{comment_id}" : nil
723 link = link_to(h("##{oid}#{comment_suffix}"), {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor}, 784 link = link_to(h("##{oid}#{comment_suffix}"),
724 :class => issue.css_classes, 785 {:only_path => only_path, :controller => 'issues',
725 :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})") 786 :action => 'show', :id => oid, :anchor => anchor},
787 :class => issue.css_classes,
788 :title => "#{issue.subject.truncate(100)} (#{issue.status.name})")
726 end 789 end
727 when 'document' 790 when 'document'
728 if document = Document.visible.find_by_id(oid) 791 if document = Document.visible.find_by_id(oid)
729 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, 792 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
730 :class => 'document' 793 :class => 'document'
733 if version = Version.visible.find_by_id(oid) 796 if version = Version.visible.find_by_id(oid)
734 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, 797 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
735 :class => 'version' 798 :class => 'version'
736 end 799 end
737 when 'message' 800 when 'message'
738 if message = Message.visible.find_by_id(oid, :include => :parent) 801 if message = Message.visible.includes(:parent).find_by_id(oid)
739 link = link_to_message(message, {:only_path => only_path}, :class => 'message') 802 link = link_to_message(message, {:only_path => only_path}, :class => 'message')
740 end 803 end
741 when 'forum' 804 when 'forum'
742 if board = Board.visible.find_by_id(oid) 805 if board = Board.visible.find_by_id(oid)
743 link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, 806 link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
754 end 817 end
755 end 818 end
756 elsif sep == ':' 819 elsif sep == ':'
757 # removes the double quotes if any 820 # removes the double quotes if any
758 name = identifier.gsub(%r{^"(.*)"$}, "\\1") 821 name = identifier.gsub(%r{^"(.*)"$}, "\\1")
822 name = CGI.unescapeHTML(name)
759 case prefix 823 case prefix
760 when 'document' 824 when 'document'
761 if project && document = project.documents.visible.find_by_title(name) 825 if project && document = project.documents.visible.find_by_title(name)
762 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, 826 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
763 :class => 'document' 827 :class => 'document'
788 end 852 end
789 if prefix == 'commit' 853 if prefix == 'commit'
790 if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first) 854 if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
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}, 855 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},
792 :class => 'changeset', 856 :class => 'changeset',
793 :title => truncate_single_line(changeset.comments, :length => 100) 857 :title => truncate_single_line_raw(changeset.comments, 100)
794 end 858 end
795 else 859 else
796 if repository && User.current.allowed_to?(:browse_repository, project) 860 if repository && User.current.allowed_to?(:browse_repository, project)
797 name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$} 861 name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$}
798 path, rev, anchor = $1, $3, $5 862 path, rev, anchor = $1, $3, $5
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, 863 link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
800 :path => to_path_param(path), 864 :path => to_path_param(path),
801 :rev => rev, 865 :rev => rev,
802 :anchor => anchor}, 866 :anchor => anchor},
803 :class => (prefix == 'export' ? 'source download' : 'source') 867 :class => (prefix == 'export' ? 'source download' : 'source')
804 end 868 end
805 end 869 end
806 repo_prefix = nil 870 repo_prefix = nil
807 end 871 end
808 when 'attachment' 872 when 'attachment'
809 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil) 873 attachments = options[:attachments] || []
874 attachments += obj.attachments if obj.respond_to?(:attachments)
810 if attachments && attachment = Attachment.latest_attach(attachments, name) 875 if attachments && attachment = Attachment.latest_attach(attachments, name)
811 link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment') 876 link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment')
812 end 877 end
813 when 'project' 878 when 'project'
814 if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first 879 if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
912 h(all) 977 h(all)
913 end 978 end
914 end 979 end
915 end 980 end
916 981
917 TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) 982 TOC_RE = /<p>\{\{((<|&lt;)|(>|&gt;))?toc\}\}<\/p>/i unless const_defined?(:TOC_RE)
918 983
919 # Renders the TOC with given headings 984 # Renders the TOC with given headings
920 def replace_toc(text, headings) 985 def replace_toc(text, headings)
921 text.gsub!(TOC_RE) do 986 text.gsub!(TOC_RE) do
987 left_align, right_align = $2, $3
922 # Keep only the 4 first levels 988 # Keep only the 4 first levels
923 headings = headings.select{|level, anchor, item| level <= 4} 989 headings = headings.select{|level, anchor, item| level <= 4}
924 if headings.empty? 990 if headings.empty?
925 '' 991 ''
926 else 992 else
927 div_class = 'toc' 993 div_class = 'toc'
928 div_class << ' right' if $1 == '>' 994 div_class << ' right' if right_align
929 div_class << ' left' if $1 == '<' 995 div_class << ' left' if left_align
930 out = "<ul class=\"#{div_class}\"><li>" 996 out = "<ul class=\"#{div_class}\"><li>"
931 root = headings.map(&:first).min 997 root = headings.map(&:first).min
932 current = root 998 current = root
933 started = false 999 started = false
934 headings.each do |level, anchor, item| 1000 headings.each do |level, anchor, item|
1225 end 1291 end
1226 tags 1292 tags
1227 end 1293 end
1228 1294
1229 def favicon 1295 def favicon
1230 "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />".html_safe 1296 "<link rel='shortcut icon' href='#{favicon_path}' />".html_safe
1297 end
1298
1299 # Returns the path to the favicon
1300 def favicon_path
1301 icon = (current_theme && current_theme.favicon?) ? current_theme.favicon_path : '/favicon.ico'
1302 image_path(icon)
1303 end
1304
1305 # Returns the full URL to the favicon
1306 def favicon_url
1307 # TODO: use #image_url introduced in Rails4
1308 path = favicon_path
1309 base = url_for(:controller => 'welcome', :action => 'index', :only_path => false)
1310 base.sub(%r{/+$},'') + '/' + path.sub(%r{^/+},'')
1231 end 1311 end
1232 1312
1233 def robot_exclusion_tag 1313 def robot_exclusion_tag
1234 '<meta name="robots" content="noindex,follow,noarchive" />'.html_safe 1314 '<meta name="robots" content="noindex,follow,noarchive" />'.html_safe
1235 end 1315 end