Feature #39997 » 39997-WIP-20240713.patch
| app/helpers/application_helper.rb | ||
|---|---|---|
| 251 | 251 |
end |
| 252 | 252 | |
| 253 | 253 |
# Helper that formats object for html or text rendering |
| 254 |
def format_object(object, html=true, &block) |
|
| 254 |
def format_object(object, *args, &block) |
|
| 255 |
options = args.last.is_a?(Hash) ? args.pop : {}
|
|
| 256 |
# The :html option is supposed to be passed as a keyword argument like `format_object(object, html: true)`, |
|
| 257 |
# but a old syntax like `format_object(object, true)` is also supported for backward compatibility. |
|
| 258 |
# TODO: Remove the old syntax in Redmine 7.0. |
|
| 259 |
html = options.fetch(:html, args[0].nil? ? true : args[0]) |
|
| 260 |
th_sep = options[:thousand_separator] || false |
|
| 261 | ||
| 255 | 262 |
if block |
| 256 | 263 |
object = yield object |
| 257 | 264 |
end |
| 258 | 265 |
case object |
| 259 | 266 |
when Array |
| 260 |
formatted_objects = object.map {|o| format_object(o, html)}
|
|
| 267 |
formatted_objects = object.map {|o| format_object(o, html: html, thousand_separator: th_sep)}
|
|
| 261 | 268 |
html ? safe_join(formatted_objects, ', ') : formatted_objects.join(', ')
|
| 262 | 269 |
when Time, ActiveSupport::TimeWithZone |
| 263 | 270 |
format_time(object) |
| 264 | 271 |
when Date |
| 265 | 272 |
format_date(object) |
| 266 | 273 |
when Integer |
| 267 |
object.to_s |
|
| 274 |
delimiter = th_sep ? ::I18n.t('number.format.delimiter') : nil
|
|
| 275 |
number_with_delimiter(object, delimiter: delimiter) |
|
| 268 | 276 |
when Float |
| 269 |
number_with_delimiter(sprintf('%.2f', object), delimiter: nil)
|
|
| 277 |
delimiter = th_sep ? ::I18n.t('number.format.delimiter') : nil
|
|
| 278 |
number_with_delimiter(sprintf('%.2f', object), delimiter: delimiter)
|
|
| 270 | 279 |
when User, Group |
| 271 | 280 |
html ? link_to_principal(object) : object.to_s |
| 272 | 281 |
when Project |
| ... | ... | |
| 299 | 308 | |
| 300 | 309 |
if object.custom_field |
| 301 | 310 |
f = object.custom_field.format.formatted_custom_value(self, object, html) |
| 311 |
th_sep = object.custom_field.thousand_separator? |
|
| 302 | 312 |
if f.nil? || f.is_a?(String) |
| 303 | 313 |
f |
| 304 | 314 |
else |
| 305 |
format_object(f, html, &block) |
|
| 315 |
format_object(f, html: html, thousand_separator: th_sep, &block)
|
|
| 306 | 316 |
end |
| 307 | 317 |
else |
| 308 | 318 |
object.value.to_s |
| app/helpers/custom_fields_helper.rb | ||
|---|---|---|
| 164 | 164 | |
| 165 | 165 |
# Return a string used to display a custom value |
| 166 | 166 |
def show_value(custom_value, html=true) |
| 167 |
format_object(custom_value, html) |
|
| 167 |
format_object(custom_value, html: html)
|
|
| 168 | 168 |
end |
| 169 | 169 | |
| 170 | 170 |
# Return a string used to display a custom value |
| 171 | 171 |
def format_value(value, custom_field) |
| 172 |
format_object(custom_field.format.formatted_value(self, custom_field, value, false), false) |
|
| 172 |
format_object(custom_field.format.formatted_value(self, custom_field, value, false), html: false)
|
|
| 173 | 173 |
end |
| 174 | 174 | |
| 175 | 175 |
# Return an array of custom field formats which can be used in select_tag |
| app/helpers/queries_helper.rb | ||
|---|---|---|
| 305 | 305 |
when :watcher_users |
| 306 | 306 |
value.to_a.join("\n")
|
| 307 | 307 |
else |
| 308 |
format_object(value, false) do |value| |
|
| 308 |
format_object(value, html: false) do |value|
|
|
| 309 | 309 |
case value.class.name |
| 310 | 310 |
when 'Float' |
| 311 | 311 |
sprintf("%.2f", value).gsub('.', l(:general_csv_decimal_separator))
|
| app/helpers/roles_helper.rb | ||
|---|---|---|
| 35 | 35 |
] |
| 36 | 36 |
fields = names + roles.collect do |role| |
| 37 | 37 |
if role.setable_permissions.include?(p) |
| 38 |
format_object(role.permissions.include?(p.name), false) |
|
| 38 |
format_object(role.permissions.include?(p.name), html: false)
|
|
| 39 | 39 |
else |
| 40 | 40 |
'' |
| 41 | 41 |
end |
| app/helpers/timelog_helper.rb | ||
|---|---|---|
| 84 | 84 |
"##{obj.id}"
|
| 85 | 85 |
end |
| 86 | 86 |
else |
| 87 |
format_object(obj, html) |
|
| 87 |
format_object(obj, html: html)
|
|
| 88 | 88 |
end |
| 89 | 89 |
elsif cf = criteria_options[:custom_field] |
| 90 | 90 |
format_value(value, cf) |
| app/models/custom_field.rb | ||
|---|---|---|
| 100 | 100 |
'user_role', |
| 101 | 101 |
'version_status', |
| 102 | 102 |
'extensions_allowed', |
| 103 |
'full_width_layout') |
|
| 103 |
'full_width_layout', |
|
| 104 |
'thousand_separator' |
|
| 105 |
) |
|
| 104 | 106 | |
| 105 | 107 |
def copy_from(arg, options={})
|
| 106 | 108 |
return if arg.blank? |
| ... | ... | |
| 225 | 227 |
text_formatting == 'full' |
| 226 | 228 |
end |
| 227 | 229 | |
| 230 |
def thousand_separator? |
|
| 231 |
thousand_separator == '1' |
|
| 232 |
end |
|
| 233 | ||
| 228 | 234 |
# Returns a ORDER BY clause that can used to sort customized |
| 229 | 235 |
# objects by their value of the custom field. |
| 230 | 236 |
# Returns nil if the custom field can not be used for sorting. |
| app/views/custom_fields/formats/_numeric.html.erb | ||
|---|---|---|
| 1 | 1 |
<%= render :partial => 'custom_fields/formats/regexp', :locals => {:f => f, :custom_field => custom_field} %>
|
| 2 | 2 |
<p><%= f.text_field(:default_value) %></p> |
| 3 |
<p><%= f.check_box :thousand_separator %></p> |
|
| 3 | 4 |
<p><%= f.text_field :url_pattern, :size => 50, :label => :label_link_values_to %></p> |
| config/locales/en.yml | ||
|---|---|---|
| 74 | 74 |
number: |
| 75 | 75 |
format: |
| 76 | 76 |
separator: "." |
| 77 |
delimiter: "" |
|
| 77 |
delimiter: ","
|
|
| 78 | 78 |
precision: 3 |
| 79 | 79 | |
| 80 | 80 |
human: |
| lib/redmine/field_format.rb | ||
|---|---|---|
| 250 | 250 |
casted = cast_value(custom_field, value, customized) |
| 251 | 251 |
if html && custom_field.url_pattern.present? |
| 252 | 252 |
texts_and_urls = Array.wrap(casted).map do |single_value| |
| 253 |
text = view.format_object(single_value, false).to_s |
|
| 253 |
text = view.format_object(single_value, html: false).to_s
|
|
| 254 | 254 |
url = url_from_pattern(custom_field, single_value, customized) |
| 255 | 255 |
[text, url] |
| 256 | 256 |
end |
| ... | ... | |
| 476 | 476 |
class Numeric < Unbounded |
| 477 | 477 |
self.form_partial = 'custom_fields/formats/numeric' |
| 478 | 478 |
self.totalable_supported = true |
| 479 |
field_attributes :thousand_separator |
|
| 479 | 480 | |
| 480 | 481 |
def order_statement(custom_field) |
| 481 | 482 |
# Make the database cast values into numeric |
| test/unit/lib/redmine/field_format/numeric_format_test.rb | ||
|---|---|---|
| 56 | 56 |
to_test = {'en' => '1234.56', 'de' => '1234,56'}
|
| 57 | 57 |
to_test.each do |locale, expected| |
| 58 | 58 |
with_locale locale do |
| 59 |
assert_equal expected, format_object(issue.reload.custom_field_values.last, false) |
|
| 59 |
assert_equal expected, format_object(issue.reload.custom_field_values.last, html: false)
|
|
| 60 | 60 |
end |
| 61 | 61 |
end |
| 62 | 62 |
end |