Project

General

Profile

Feature #42335 » 0001-progress-bar-field-format-1168755.patch

Jens Krämer, 2025-03-02 08:51

View differences:

config/locales/de.yml
843 843
  label_year: Jahr
844 844
  label_yesterday: gestern
845 845
  label_default_query: Standardabfrage
846
  label_progressbar: Fortschrittsbalken
846 847

  
847 848
  mail_body_account_activation_request: "Ein neuer Benutzer (%{value}) hat sich registriert. Sein Konto wartet auf Ihre Genehmigung:"
848 849
  mail_body_account_information: Ihre Konto-Informationen
config/locales/en.yml
1150 1150
  label_edited: Edited
1151 1151
  label_time_by_author: "%{time} by %{author}"
1152 1152
  label_involved_principals: Author / Previous assignee
1153
  label_progressbar: Progress bar
1153 1154

  
1154 1155
  button_login: Login
1155 1156
  button_submit: Submit
config/locales/fr.yml
1025 1025
    for_this_user: For this user
1026 1026
  label_trackers_description: Description des trackers
1027 1027
  label_open_trackers_description: Afficher la description des trackers
1028
  label_progressbar: Barre de progression
1028 1029

  
1029 1030
  button_login: Connexion
1030 1031
  button_submit: Soumettre
lib/redmine/field_format.rb
1082 1082
            })
1083 1083
      end
1084 1084
    end
1085

  
1086
    class ProgressbarFormat < Numeric
1087
      add 'progressbar'
1088

  
1089
      self.form_partial = nil
1090
      self.totalable_supported = false
1091

  
1092
      def label
1093
        "label_progressbar"
1094
      end
1095

  
1096
      def cast_single_value(custom_field, value, customized=nil)
1097
        value.to_i.clamp(0, 100)
1098
      end
1099

  
1100
      def validate_single_value(custom_field, value, customized=nil)
1101
        errs = super
1102
        errs << ::I18n.t('activerecord.errors.messages.not_a_number') unless /^\d*$/.match?(value.to_s.strip)
1103
        errs << ::I18n.t('activerecord.errors.messages.invalid') unless value.to_i.between?(0, 100)
1104
        errs
1105
      end
1106

  
1107
      def query_filter_options(custom_field, query)
1108
        {:type => :integer}
1109
      end
1110

  
1111
      def group_statement(custom_field)
1112
        order_statement(custom_field)
1113
      end
1114

  
1115
      def edit_tag(view, tag_id, tag_name, custom_value, options={})
1116
        view.select_tag tag_name, view.options_for_select((0..100).step(Setting.issue_done_ratio_interval.to_i).to_a.collect {|r| ["#{r} %", r]}, custom_value.value), options.merge(id: tag_id, style: "width: 75px;")
1117
      end
1118

  
1119
      def bulk_edit_tag(view, tag_id, tag_name, custom_field, objects, value, options={})
1120
        opts = view.options_for_select([[l(:label_no_change_option), '']] + (0..100).step(Setting.issue_done_ratio_interval.to_i).to_a.collect {|r| ["#{r} %", r]})
1121
        view.select_tag(tag_name, opts, options.merge(id: tag_id, style: "width: 75px;")) +
1122
          bulk_clear_tag(view, tag_id, tag_name, custom_field, value)
1123
      end
1124

  
1125
      def formatted_value(view, custom_field, value, customized=nil, html=false)
1126
        text = "#{value}%"
1127
        if html
1128
          view.progress_bar(value.to_i, legend: (text if view.action_name == 'show'))
1129
        else
1130
          text
1131
        end
1132
      end
1133
    end
1085 1134
  end
1086 1135
end
test/unit/lib/redmine/field_format/progressbar_format_test.rb
1
require_relative '../../../../test_helper'
2
require 'redmine/field_format'
3

  
4
module Redmine::FieldFormat
5
  class ProgressbarFormatTest < ActiveSupport::TestCase
6

  
7
    def setup
8
      @field = IssueCustomField.new(name: 'ProgressbarTest', field_format: 'progressbar')
9
      @format = Redmine::FieldFormat::ProgressbarFormat.instance
10
    end
11

  
12
    def test_validate_invalid_value
13
      cv = CustomValue.new(custom_field: @field, value: '120')
14
      assert_include ::I18n.t('activerecord.errors.messages.invalid'), @format.validate_custom_value(cv)
15
    end
16

  
17
    def test_validate_numericality
18
      cv = CustomValue.new(custom_field: @field, value: 'abc')
19
      assert_include ::I18n.t('activerecord.errors.messages.not_a_number'), @format.validate_custom_value(cv)
20
    end
21

  
22
    def test_cast_value_clamping
23
      assert_equal 0, @field.cast_value('-10')
24
      assert_equal 0, @field.cast_value('0')
25
      assert_equal 50, @field.cast_value('50')
26
      assert_equal 100, @field.cast_value('120')
27
    end
28

  
29
    def test_empty_value
30
      assert_nil @field.cast_value('')
31
    end
32

  
33
    def test_totalable_support
34
      assert_not @format.totalable_supported?
35
    end
36

  
37
    def test_validate_non_numeric_value_should_fail
38
      assert_include ::I18n.t('activerecord.errors.messages.not_a_number'),
39
        @format.validate_single_value(@field, "abc")
40
    end
41

  
42
    def test_validate_negative_value_should_fail 
43
      assert_include ::I18n.t('activerecord.errors.messages.invalid'),
44
        @format.validate_single_value(@field, "-10")
45
    end
46

  
47
    def test_validate_value_above_100_should_fail
48
      assert_include ::I18n.t('activerecord.errors.messages.invalid'),
49
        @format.validate_single_value(@field, "150")
50
    end
51

  
52
    def test_validate_valid_value_should_pass
53
      assert_empty @format.validate_single_value(@field, "50")
54
      assert_empty @format.validate_single_value(@field, "0")
55
      assert_empty @format.validate_single_value(@field, "100")
56
    end
57

  
58
    def test_validate_blank_value_should_pass
59
      assert_empty @format.validate_single_value(@field, "")
60
    end
61

  
62
    def test_query_filter_options
63
      options = @format.query_filter_options(@field, nil)
64
      assert_equal :integer, options[:type]
65
    end
66

  
67
  end
68
end
69

  
(4-4/5)