diff --git a/config/locales/de.yml b/config/locales/de.yml index 4947ead29..d97a07e2d 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -843,6 +843,7 @@ de: label_year: Jahr label_yesterday: gestern label_default_query: Standardabfrage + label_progressbar: Fortschrittsbalken mail_body_account_activation_request: "Ein neuer Benutzer (%{value}) hat sich registriert. Sein Konto wartet auf Ihre Genehmigung:" mail_body_account_information: Ihre Konto-Informationen diff --git a/config/locales/en.yml b/config/locales/en.yml index aa15095c6..aac5afe6b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1150,6 +1150,7 @@ en: label_edited: Edited label_time_by_author: "%{time} by %{author}" label_involved_principals: Author / Previous assignee + label_progressbar: Progress bar button_login: Login button_submit: Submit diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 5319feccf..aba16b6fe 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1025,6 +1025,7 @@ fr: for_this_user: For this user label_trackers_description: Description des trackers label_open_trackers_description: Afficher la description des trackers + label_progressbar: Barre de progression button_login: Connexion button_submit: Soumettre diff --git a/lib/redmine/field_format.rb b/lib/redmine/field_format.rb index b41b2986c..c4fd1b592 100644 --- a/lib/redmine/field_format.rb +++ b/lib/redmine/field_format.rb @@ -1082,5 +1082,61 @@ module Redmine }) end end + + class ProgressbarFormat < Numeric + add 'progressbar' + + self.form_partial = nil + self.totalable_supported = false + + def label + "label_progressbar" + end + + def cast_single_value(custom_field, value, customized=nil) + value.to_i.clamp(0, 100) + end + + def validate_single_value(custom_field, value, customized=nil) + errs = super + errs << ::I18n.t('activerecord.errors.messages.not_a_number') unless /^\d*$/.match?(value.to_s.strip) + errs << ::I18n.t('activerecord.errors.messages.invalid') unless value.to_i.between?(0, 100) + errs + end + + def query_filter_options(custom_field, query) + {:type => :integer} + end + + def group_statement(custom_field) + order_statement(custom_field) + end + + def edit_tag(view, tag_id, tag_name, custom_value, options={}) + 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;") + ) + end + + def bulk_edit_tag(view, tag_id, tag_name, custom_field, objects, value, options={}) + 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]}) + view.select_tag(tag_name, opts, options.merge(id: tag_id, style: "width: 75px;")) + + bulk_clear_tag(view, tag_id, tag_name, custom_field, value) + end + + def formatted_value(view, custom_field, value, customized=nil, html=false) + text = "#{value}%" + if html + view.progress_bar(value.to_i, legend: (text if view.action_name == 'show')) + else + text + end + end + end end end diff --git a/test/unit/lib/redmine/field_format/progressbar_format_test.rb b/test/unit/lib/redmine/field_format/progressbar_format_test.rb new file mode 100644 index 000000000..d507f9ddb --- /dev/null +++ b/test/unit/lib/redmine/field_format/progressbar_format_test.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006- Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require_relative '../../../../test_helper' +require 'redmine/field_format' + +module Redmine::FieldFormat + class ProgressbarFormatTest < ActiveSupport::TestCase + def setup + @field = IssueCustomField.new(name: 'ProgressbarTest', field_format: 'progressbar') + @format = Redmine::FieldFormat::ProgressbarFormat.instance + end + + def test_validate_invalid_value + cv = CustomValue.new(custom_field: @field, value: '120') + assert_include ::I18n.t('activerecord.errors.messages.invalid'), @format.validate_custom_value(cv) + end + + def test_validate_numericality + cv = CustomValue.new(custom_field: @field, value: 'abc') + assert_include ::I18n.t('activerecord.errors.messages.not_a_number'), @format.validate_custom_value(cv) + end + + def test_cast_value_clamping + assert_equal 0, @field.cast_value('-10') + assert_equal 0, @field.cast_value('0') + assert_equal 50, @field.cast_value('50') + assert_equal 100, @field.cast_value('120') + end + + def test_empty_value + assert_nil @field.cast_value('') + end + + def test_totalable_support + assert_not @format.totalable_supported? + end + + def test_validate_non_numeric_value_should_fail + assert_include ::I18n.t('activerecord.errors.messages.not_a_number'), + @format.validate_single_value(@field, "abc") + end + + def test_validate_negative_value_should_fail + assert_include ::I18n.t('activerecord.errors.messages.invalid'), + @format.validate_single_value(@field, "-10") + end + + def test_validate_value_above_100_should_fail + assert_include ::I18n.t('activerecord.errors.messages.invalid'), + @format.validate_single_value(@field, "150") + end + + def test_validate_valid_value_should_pass + assert_empty @format.validate_single_value(@field, "50") + assert_empty @format.validate_single_value(@field, "0") + assert_empty @format.validate_single_value(@field, "100") + end + + def test_validate_blank_value_should_pass + assert_empty @format.validate_single_value(@field, "") + end + + def test_query_filter_options + options = @format.query_filter_options(@field, nil) + assert_equal :integer, options[:type] + end + end +end