annotate app/helpers/issues_helper.rb @ 45:65d9e2cabaa3 luisf

Added tipoftheday to the config/settings in order to correct previous issues. Tip of the day is now working correctly. Added the heading strings to the locales files.
author luisf
date Tue, 23 Nov 2010 11:50:01 +0000
parents 94944d00e43c
children af80e5618e9b
rev   line source
Chris@0 1 # redMine - project management software
Chris@0 2 # Copyright (C) 2006 Jean-Philippe Lang
Chris@0 3 #
Chris@0 4 # This program is free software; you can redistribute it and/or
Chris@0 5 # modify it under the terms of the GNU General Public License
Chris@0 6 # as published by the Free Software Foundation; either version 2
Chris@0 7 # of the License, or (at your option) any later version.
Chris@0 8 #
Chris@0 9 # This program is distributed in the hope that it will be useful,
Chris@0 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 12 # GNU General Public License for more details.
Chris@0 13 #
Chris@0 14 # You should have received a copy of the GNU General Public License
Chris@0 15 # along with this program; if not, write to the Free Software
Chris@0 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Chris@0 17
Chris@0 18 module IssuesHelper
Chris@0 19 include ApplicationHelper
Chris@0 20
Chris@0 21 def issue_list(issues, &block)
Chris@0 22 ancestors = []
Chris@0 23 issues.each do |issue|
Chris@0 24 while (ancestors.any? && !issue.is_descendant_of?(ancestors.last))
Chris@0 25 ancestors.pop
Chris@0 26 end
Chris@0 27 yield issue, ancestors.size
Chris@0 28 ancestors << issue unless issue.leaf?
Chris@0 29 end
Chris@0 30 end
chris@22 31
chris@22 32 # Renders a HTML/CSS tooltip
chris@22 33 #
chris@22 34 # To use, a trigger div is needed. This is a div with the class of "tooltip"
chris@22 35 # that contains this method wrapped in a span with the class of "tip"
chris@22 36 #
chris@22 37 # <div class="tooltip"><%= link_to_issue(issue) %>
chris@22 38 # <span class="tip"><%= render_issue_tooltip(issue) %></span>
chris@22 39 # </div>
chris@22 40 #
Chris@0 41 def render_issue_tooltip(issue)
Chris@14 42 @cached_label_status ||= l(:field_status)
Chris@0 43 @cached_label_start_date ||= l(:field_start_date)
Chris@0 44 @cached_label_due_date ||= l(:field_due_date)
Chris@0 45 @cached_label_assigned_to ||= l(:field_assigned_to)
Chris@0 46 @cached_label_priority ||= l(:field_priority)
chris@22 47 @cached_label_project ||= l(:field_project)
chris@22 48
Chris@0 49 link_to_issue(issue) + "<br /><br />" +
chris@22 50 "<strong>#{@cached_label_project}</strong>: #{link_to_project(issue.project)}<br />" +
Chris@14 51 "<strong>#{@cached_label_status}</strong>: #{issue.status.name}<br />" +
Chris@0 52 "<strong>#{@cached_label_start_date}</strong>: #{format_date(issue.start_date)}<br />" +
Chris@0 53 "<strong>#{@cached_label_due_date}</strong>: #{format_date(issue.due_date)}<br />" +
Chris@0 54 "<strong>#{@cached_label_assigned_to}</strong>: #{issue.assigned_to}<br />" +
Chris@0 55 "<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}"
Chris@0 56 end
Chris@0 57
Chris@0 58 def render_issue_subject_with_tree(issue)
Chris@0 59 s = ''
Chris@0 60 issue.ancestors.each do |ancestor|
Chris@0 61 s << '<div>' + content_tag('p', link_to_issue(ancestor))
Chris@0 62 end
Chris@0 63 s << '<div>' + content_tag('h3', h(issue.subject))
Chris@0 64 s << '</div>' * (issue.ancestors.size + 1)
Chris@0 65 s
Chris@0 66 end
Chris@0 67
Chris@0 68 def render_descendants_tree(issue)
Chris@0 69 s = '<form><table class="list issues">'
Chris@0 70 issue_list(issue.descendants.sort_by(&:lft)) do |child, level|
Chris@0 71 s << content_tag('tr',
Chris@0 72 content_tag('td', check_box_tag("ids[]", child.id, false, :id => nil), :class => 'checkbox') +
Chris@0 73 content_tag('td', link_to_issue(child, :truncate => 60), :class => 'subject') +
Chris@0 74 content_tag('td', h(child.status)) +
Chris@0 75 content_tag('td', link_to_user(child.assigned_to)) +
Chris@0 76 content_tag('td', progress_bar(child.done_ratio, :width => '80px')),
Chris@0 77 :class => "issue issue-#{child.id} hascontextmenu #{level > 0 ? "idnt idnt-#{level}" : nil}")
Chris@0 78 end
Chris@0 79 s << '</form></table>'
Chris@0 80 s
Chris@0 81 end
Chris@0 82
Chris@0 83 def render_custom_fields_rows(issue)
Chris@0 84 return if issue.custom_field_values.empty?
Chris@0 85 ordered_values = []
Chris@0 86 half = (issue.custom_field_values.size / 2.0).ceil
Chris@0 87 half.times do |i|
Chris@0 88 ordered_values << issue.custom_field_values[i]
Chris@0 89 ordered_values << issue.custom_field_values[i + half]
Chris@0 90 end
Chris@0 91 s = "<tr>\n"
Chris@0 92 n = 0
Chris@0 93 ordered_values.compact.each do |value|
Chris@0 94 s << "</tr>\n<tr>\n" if n > 0 && (n % 2) == 0
Chris@0 95 s << "\t<th>#{ h(value.custom_field.name) }:</th><td>#{ simple_format_without_paragraph(h(show_value(value))) }</td>\n"
Chris@0 96 n += 1
Chris@0 97 end
Chris@0 98 s << "</tr>\n"
Chris@0 99 s
Chris@0 100 end
Chris@0 101
Chris@0 102 def sidebar_queries
Chris@0 103 unless @sidebar_queries
Chris@0 104 # User can see public queries and his own queries
Chris@0 105 visible = ARCondition.new(["is_public = ? OR user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
Chris@0 106 # Project specific queries and global queries
Chris@0 107 visible << (@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id])
Chris@0 108 @sidebar_queries = Query.find(:all,
Chris@0 109 :select => 'id, name',
Chris@0 110 :order => "name ASC",
Chris@0 111 :conditions => visible.conditions)
Chris@0 112 end
Chris@0 113 @sidebar_queries
Chris@0 114 end
Chris@0 115
Chris@0 116 def show_detail(detail, no_html=false)
Chris@0 117 case detail.property
Chris@0 118 when 'attr'
Chris@0 119 field = detail.prop_key.to_s.gsub(/\_id$/, "")
Chris@0 120 label = l(("field_" + field).to_sym)
Chris@0 121 case
Chris@0 122 when ['due_date', 'start_date'].include?(detail.prop_key)
Chris@0 123 value = format_date(detail.value.to_date) if detail.value
Chris@0 124 old_value = format_date(detail.old_value.to_date) if detail.old_value
Chris@0 125
Chris@0 126 when ['project_id', 'status_id', 'tracker_id', 'assigned_to_id', 'priority_id', 'category_id', 'fixed_version_id'].include?(detail.prop_key)
Chris@0 127 value = find_name_by_reflection(field, detail.value)
Chris@0 128 old_value = find_name_by_reflection(field, detail.old_value)
Chris@0 129
Chris@0 130 when detail.prop_key == 'estimated_hours'
Chris@0 131 value = "%0.02f" % detail.value.to_f unless detail.value.blank?
Chris@0 132 old_value = "%0.02f" % detail.old_value.to_f unless detail.old_value.blank?
Chris@0 133
Chris@0 134 when detail.prop_key == 'parent_id'
Chris@0 135 label = l(:field_parent_issue)
Chris@0 136 value = "##{detail.value}" unless detail.value.blank?
Chris@0 137 old_value = "##{detail.old_value}" unless detail.old_value.blank?
Chris@0 138 end
Chris@0 139 when 'cf'
Chris@0 140 custom_field = CustomField.find_by_id(detail.prop_key)
Chris@0 141 if custom_field
Chris@0 142 label = custom_field.name
Chris@0 143 value = format_value(detail.value, custom_field.field_format) if detail.value
Chris@0 144 old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value
Chris@0 145 end
Chris@0 146 when 'attachment'
Chris@0 147 label = l(:label_attachment)
Chris@0 148 end
Chris@0 149 call_hook(:helper_issues_show_detail_after_setting, {:detail => detail, :label => label, :value => value, :old_value => old_value })
Chris@0 150
Chris@0 151 label ||= detail.prop_key
Chris@0 152 value ||= detail.value
Chris@0 153 old_value ||= detail.old_value
Chris@0 154
Chris@0 155 unless no_html
Chris@0 156 label = content_tag('strong', label)
Chris@0 157 old_value = content_tag("i", h(old_value)) if detail.old_value
Chris@0 158 old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?)
Chris@0 159 if detail.property == 'attachment' && !value.blank? && a = Attachment.find_by_id(detail.prop_key)
Chris@0 160 # Link to the attachment if it has not been removed
Chris@0 161 value = link_to_attachment(a)
Chris@0 162 else
Chris@0 163 value = content_tag("i", h(value)) if value
Chris@0 164 end
Chris@0 165 end
Chris@0 166
Chris@0 167 if !detail.value.blank?
Chris@0 168 case detail.property
Chris@0 169 when 'attr', 'cf'
Chris@0 170 if !detail.old_value.blank?
Chris@0 171 l(:text_journal_changed, :label => label, :old => old_value, :new => value)
Chris@0 172 else
Chris@0 173 l(:text_journal_set_to, :label => label, :value => value)
Chris@0 174 end
Chris@0 175 when 'attachment'
Chris@0 176 l(:text_journal_added, :label => label, :value => value)
Chris@0 177 end
Chris@0 178 else
Chris@0 179 l(:text_journal_deleted, :label => label, :old => old_value)
Chris@0 180 end
Chris@0 181 end
Chris@0 182
Chris@0 183 # Find the name of an associated record stored in the field attribute
Chris@0 184 def find_name_by_reflection(field, id)
Chris@0 185 association = Issue.reflect_on_association(field.to_sym)
Chris@0 186 if association
Chris@0 187 record = association.class_name.constantize.find_by_id(id)
Chris@0 188 return record.name if record
Chris@0 189 end
Chris@0 190 end
Chris@0 191
Chris@0 192 def issues_to_csv(issues, project = nil)
Chris@0 193 ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
Chris@0 194 decimal_separator = l(:general_csv_decimal_separator)
Chris@0 195 export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
Chris@0 196 # csv header fields
Chris@0 197 headers = [ "#",
Chris@0 198 l(:field_status),
Chris@0 199 l(:field_project),
Chris@0 200 l(:field_tracker),
Chris@0 201 l(:field_priority),
Chris@0 202 l(:field_subject),
Chris@0 203 l(:field_assigned_to),
Chris@0 204 l(:field_category),
Chris@0 205 l(:field_fixed_version),
Chris@0 206 l(:field_author),
Chris@0 207 l(:field_start_date),
Chris@0 208 l(:field_due_date),
Chris@0 209 l(:field_done_ratio),
Chris@0 210 l(:field_estimated_hours),
Chris@0 211 l(:field_parent_issue),
Chris@0 212 l(:field_created_on),
Chris@0 213 l(:field_updated_on)
Chris@0 214 ]
Chris@0 215 # Export project custom fields if project is given
Chris@0 216 # otherwise export custom fields marked as "For all projects"
Chris@0 217 custom_fields = project.nil? ? IssueCustomField.for_all : project.all_issue_custom_fields
Chris@0 218 custom_fields.each {|f| headers << f.name}
Chris@0 219 # Description in the last column
Chris@0 220 headers << l(:field_description)
Chris@0 221 csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
Chris@0 222 # csv lines
Chris@0 223 issues.each do |issue|
Chris@0 224 fields = [issue.id,
Chris@0 225 issue.status.name,
Chris@0 226 issue.project.name,
Chris@0 227 issue.tracker.name,
Chris@0 228 issue.priority.name,
Chris@0 229 issue.subject,
Chris@0 230 issue.assigned_to,
Chris@0 231 issue.category,
Chris@0 232 issue.fixed_version,
Chris@0 233 issue.author.name,
Chris@0 234 format_date(issue.start_date),
Chris@0 235 format_date(issue.due_date),
Chris@0 236 issue.done_ratio,
Chris@0 237 issue.estimated_hours.to_s.gsub('.', decimal_separator),
Chris@0 238 issue.parent_id,
Chris@0 239 format_time(issue.created_on),
Chris@0 240 format_time(issue.updated_on)
Chris@0 241 ]
Chris@0 242 custom_fields.each {|f| fields << show_value(issue.custom_value_for(f)) }
Chris@0 243 fields << issue.description
Chris@0 244 csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
Chris@0 245 end
Chris@0 246 end
Chris@0 247 export
Chris@0 248 end
Chris@0 249 end