From 3433731585b6126208cd855b46115d18d249fb1f Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Thu, 2 May 2024 20:23:05 +0000 Subject: [PATCH 001/459] Switches from MD5 to SHA256 when computing the hash for gravatar URL (#40652). git-svn-id: https://svn.redmine.org/redmine/trunk@22802 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/plugins/gravatar/lib/gravatar.rb | 3 +-- test/helpers/avatars_helper_test.rb | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/plugins/gravatar/lib/gravatar.rb b/lib/plugins/gravatar/lib/gravatar.rb index ea4a37cb5a0..4dc27db52b6 100644 --- a/lib/plugins/gravatar/lib/gravatar.rb +++ b/lib/plugins/gravatar/lib/gravatar.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require 'digest/md5' require 'cgi' module GravatarHelper @@ -65,7 +64,7 @@ def gravatar_api_url(hash) # Return the gravatar URL for the given email address. def gravatar_url(email, options={}) - email_hash = Digest::MD5.hexdigest(email) + email_hash = Digest::SHA256.hexdigest(email) options = DEFAULT_OPTIONS.merge(options) options[:default] = CGI::escape(options[:default]) unless options[:default].nil? gravatar_api_url(email_hash).tap do |url| diff --git a/test/helpers/avatars_helper_test.rb b/test/helpers/avatars_helper_test.rb index 03a4b1ea138..06c4d599313 100644 --- a/test/helpers/avatars_helper_test.rb +++ b/test/helpers/avatars_helper_test.rb @@ -31,11 +31,11 @@ def setup end def test_avatar_with_user - assert_include Digest::MD5.hexdigest('jsmith@somenet.foo'), avatar(User.find_by_mail('jsmith@somenet.foo')) + assert_include Digest::SHA256.hexdigest('jsmith@somenet.foo'), avatar(User.find_by_mail('jsmith@somenet.foo')) end def test_avatar_with_email_string - assert_include Digest::MD5.hexdigest('jsmith@somenet.foo'), avatar('jsmith ') + assert_include Digest::SHA256.hexdigest('jsmith@somenet.foo'), avatar('jsmith ') end def test_avatar_with_anonymous_user From cd8d4fe444328925a71b9018dac8b6194801d547 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Thu, 2 May 2024 20:58:03 +0000 Subject: [PATCH 002/459] Progress of version should be calculated the same way as parent tasks (#24457, #4682). git-svn-id: https://svn.redmine.org/redmine/trunk@22803 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/version.rb | 17 +++++++++++------ test/unit/version_test.rb | 10 ++++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/app/models/version.rb b/app/models/version.rb index 17e1128e488..e1525f9a0cb 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -78,9 +78,11 @@ def load_counts # Used to weight unestimated issues in progress calculation def estimated_average if @estimated_average.nil? - average = average(:estimated_hours).to_f - if average == 0 - average = 1 + issues_with_total_estimated_hours = select {|c| c.total_estimated_hours.to_f > 0.0} + if issues_with_total_estimated_hours.any? + average = issues_with_total_estimated_hours.map(&:total_estimated_hours).sum.to_f / issues_with_total_estimated_hours.count + else + average = 1.0 end @estimated_average = average end @@ -98,9 +100,12 @@ def issues_progress(open) @issues_progress[open] ||= begin progress = 0 if count > 0 - ratio = open ? 'done_ratio' : 100 - - done = open(open).sum("COALESCE(estimated_hours, #{estimated_average}) * #{ratio}").to_f + done = open(open).map {|c| + estimated = c.total_estimated_hours.to_f + estimated = estimated_average unless estimated > 0.0 + ratio = c.closed? ? 100 : (c.done_ratio || 0) + estimated * ratio + }.sum progress = done / (estimated_average * count) end progress diff --git a/test/unit/version_test.rb b/test/unit/version_test.rb index 45c5bed3734..4b20c05a006 100644 --- a/test/unit/version_test.rb +++ b/test/unit/version_test.rb @@ -117,6 +117,16 @@ def test_progress_should_consider_closed_issues_as_completed assert_progress_equal (100.0)/3, v.closed_percent end + def test_progress_should_consider_closed_issues_with_0h_estimated_as_completed + project = Project.find(1) + closed = IssueStatus.where(:is_closed => true).first + v = Version.create!(:project => project, :name => 'Progress') + add_issue(v, :done_ratio => 100, :estimated_hours => 0) + add_issue(v, :done_ratio => 100, :estimated_hours => 0, :status => closed) + assert_progress_equal 100, v.completed_percent + assert_progress_equal 50, v.closed_percent + end + def test_progress_should_consider_estimated_hours_to_weight_issues project = Project.find(1) v = Version.create!(:project => project, :name => 'Progress') From 3822b633ef53eceb2ff34f985572a6011ebcae3a Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Thu, 2 May 2024 21:15:43 +0000 Subject: [PATCH 003/459] Adds test for #24457. git-svn-id: https://svn.redmine.org/redmine/trunk@22804 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/version_test.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/unit/version_test.rb b/test/unit/version_test.rb index 4b20c05a006..d3f1e5aa24b 100644 --- a/test/unit/version_test.rb +++ b/test/unit/version_test.rb @@ -149,6 +149,20 @@ def test_progress_should_consider_average_estimated_hours_to_weight_unestimated_ assert_progress_equal 25.0/100.0*100, v.closed_percent end + def test_progress_should_be_weighted_by_estimated_times_if_any_with_grandchildren + project = Project.find(1) + v = Version.create!(:project => project, :name => 'Progress') + with_settings :parent_issue_done_ratio => 'derived' do + parent = Issue.generate! + parent.generate_child!(:estimated_hours => 2, :done_ratio => 0, :fixed_version => v) + child = parent.generate_child!( :fixed_version => v) + child.generate_child!(:estimated_hours => 2, :done_ratio => 50) + child.generate_child!(:estimated_hours => 2, :done_ratio => 50) + + assert_progress_equal 200.0 / (3.0 * 2), v.completed_percent + end + end + def test_should_sort_scheduled_then_unscheduled_versions Version.delete_all v4 = Version.create!(:project_id => 1, :name => 'v4') From 1a96ee225dd4ebc58848c3459804a4254837a01f Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Thu, 2 May 2024 21:35:16 +0000 Subject: [PATCH 004/459] Fixes RuboCop offense Performance/Sum (#24457, #4682). git-svn-id: https://svn.redmine.org/redmine/trunk@22805 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/version.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/version.rb b/app/models/version.rb index e1525f9a0cb..ec1a9f77b53 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -80,7 +80,7 @@ def estimated_average if @estimated_average.nil? issues_with_total_estimated_hours = select {|c| c.total_estimated_hours.to_f > 0.0} if issues_with_total_estimated_hours.any? - average = issues_with_total_estimated_hours.map(&:total_estimated_hours).sum.to_f / issues_with_total_estimated_hours.count + average = issues_with_total_estimated_hours.sum(&:total_estimated_hours).to_f / issues_with_total_estimated_hours.count else average = 1.0 end @@ -100,12 +100,12 @@ def issues_progress(open) @issues_progress[open] ||= begin progress = 0 if count > 0 - done = open(open).map {|c| + done = open(open).sum do |c| estimated = c.total_estimated_hours.to_f estimated = estimated_average unless estimated > 0.0 ratio = c.closed? ? 100 : (c.done_ratio || 0) estimated * ratio - }.sum + end progress = done / (estimated_average * count) end progress From aaed5637b4bf2d15bb9c8b979aa0110a01578e12 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Thu, 2 May 2024 21:55:52 +0000 Subject: [PATCH 005/459] Fixes RuboCop offense Layout/SpaceInsideParens (#24457). git-svn-id: https://svn.redmine.org/redmine/trunk@22806 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/version_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/version_test.rb b/test/unit/version_test.rb index d3f1e5aa24b..d7274ca9a1a 100644 --- a/test/unit/version_test.rb +++ b/test/unit/version_test.rb @@ -155,7 +155,7 @@ def test_progress_should_be_weighted_by_estimated_times_if_any_with_grandchildre with_settings :parent_issue_done_ratio => 'derived' do parent = Issue.generate! parent.generate_child!(:estimated_hours => 2, :done_ratio => 0, :fixed_version => v) - child = parent.generate_child!( :fixed_version => v) + child = parent.generate_child!(:fixed_version => v) child.generate_child!(:estimated_hours => 2, :done_ratio => 50) child.generate_child!(:estimated_hours => 2, :done_ratio => 50) From 473db7e83b10fa233bb66e965cdf370b1a077fc3 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Fri, 3 May 2024 07:31:17 +0000 Subject: [PATCH 006/459] Fixes failing tests caused by r22802 (#40652). git-svn-id: https://svn.redmine.org/redmine/trunk@22807 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/integration/api_test/users_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/api_test/users_test.rb b/test/integration/api_test/users_test.rb index a51c14b0ece..a05fe1ee3dd 100644 --- a/test/integration/api_test/users_test.rb +++ b/test/integration/api_test/users_test.rb @@ -42,7 +42,7 @@ class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base # No one has changed password. assert_select user_element, 'passwd_changed_on', :text => '' - assert_select user_element, 'avatar_url', :text => %r|\Ahttps://gravatar.com/avatar/\h{32}\?default=mm| + assert_select user_element, 'avatar_url', :text => %r|\Ahttps://gravatar.com/avatar/\h{64}\?default=mm| if user == users.last assert_select user_element, 'twofa_scheme', :text => 'totp' @@ -167,7 +167,7 @@ class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base assert_select 'user id', :text => '2' assert_select 'user updated_on', :text => Time.zone.parse('2006-07-19T20:42:15Z').iso8601 assert_select 'user passwd_changed_on', :text => '' - assert_select 'user avatar_url', :text => %r|\Ahttps://gravatar.com/avatar/\h{32}\?default=robohash| + assert_select 'user avatar_url', :text => %r|\Ahttps://gravatar.com/avatar/\h{64}\?default=robohash| end test "GET /users/:id.xml should not return avatar_url when not set email address" do From a4abae2324ef2d420a9cc99cb9867a89e5380004 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Fri, 3 May 2024 08:24:49 +0000 Subject: [PATCH 007/459] Fixes failing tests on postgresql (#29894). git-svn-id: https://svn.redmine.org/redmine/trunk@22808 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/functional/issues_controller_test.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index 7b8147ece16..f7c87918836 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -1981,7 +1981,13 @@ def test_index_with_watchers_column_as_csv ) assert_response :success - assert_include "\"#{User.find(1).name}\n#{User.find(3).name}\"", response.body + + lines = CSV.parse(response.body) + # Issue with ID 2 is the second issue in the CSV + # Column 3 is watchers_users + watchers = lines[2][2].split("\n").sort + + assert_equal [User.find(3).name, User.find(1).name], watchers end def test_index_with_estimated_hours_total From 6ca7d4df551690fb244852619191052f26d5183c Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Fri, 3 May 2024 11:57:47 +0000 Subject: [PATCH 008/459] Fixes random failing tests. git-svn-id: https://svn.redmine.org/redmine/trunk@22809 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/query_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index 8ea079764c5..cf11bf10e4c 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -1373,7 +1373,7 @@ def test_filter_project_parent_id_with_my_bookmarks result = query.results_scope bookmarks = User.current.bookmarked_project_ids - assert_equal Project.where(parent_id: bookmarks).ids, result.map(&:id).sort + assert_equal Project.where(parent_id: bookmarks).ids.sort, result.map(&:id).sort end def test_filter_watched_issues From 6524dd3eaa9f36906060d6cf747086ee5c8ebcec Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Fri, 3 May 2024 13:04:30 +0000 Subject: [PATCH 009/459] Updates locales (#40569). git-svn-id: https://svn.redmine.org/redmine/trunk@22810 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/ar.yml | 1 + config/locales/az.yml | 1 + config/locales/bg.yml | 1 + config/locales/bs.yml | 1 + config/locales/ca.yml | 1 + config/locales/cs.yml | 1 + config/locales/da.yml | 1 + config/locales/de.yml | 1 + config/locales/el.yml | 1 + config/locales/en-GB.yml | 1 + config/locales/es-PA.yml | 1 + config/locales/es.yml | 1 + config/locales/et.yml | 1 + config/locales/eu.yml | 1 + config/locales/fa.yml | 1 + config/locales/fi.yml | 1 + config/locales/fr.yml | 1 + config/locales/gl.yml | 1 + config/locales/he.yml | 1 + config/locales/hr.yml | 1 + config/locales/hu.yml | 1 + config/locales/id.yml | 1 + config/locales/it.yml | 1 + config/locales/ja.yml | 1 + config/locales/ko.yml | 1 + config/locales/lt.yml | 1 + config/locales/lv.yml | 1 + config/locales/mk.yml | 1 + config/locales/mn.yml | 1 + config/locales/nl.yml | 1 + config/locales/no.yml | 1 + config/locales/pl.yml | 1 + config/locales/pt-BR.yml | 1 + config/locales/pt.yml | 1 + config/locales/ro.yml | 1 + config/locales/ru.yml | 1 + config/locales/sk.yml | 1 + config/locales/sl.yml | 1 + config/locales/sq.yml | 1 + config/locales/sr-YU.yml | 1 + config/locales/sr.yml | 1 + config/locales/sv.yml | 1 + config/locales/ta-IN.yml | 1 + config/locales/th.yml | 1 + config/locales/tr.yml | 1 + config/locales/uk.yml | 1 + config/locales/vi.yml | 1 + config/locales/zh-TW.yml | 1 + config/locales/zh.yml | 1 + 49 files changed, 49 insertions(+) diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 165b87d66ee..4171ff62e0f 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -1487,3 +1487,4 @@ ar: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/az.yml b/config/locales/az.yml index 2674f28c154..904b44c0503 100644 --- a/config/locales/az.yml +++ b/config/locales/az.yml @@ -1579,3 +1579,4 @@ az: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 4e55ee95bd9..e3f54f094e3 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -1432,3 +1432,4 @@ bg: text_project_destroy_enter_identifier: За да потвърдите действието, въведете идентификатора на проекта (%{identifier}) по-долу. field_name_or_email_or_login: Име, e-mail или login име label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/bs.yml b/config/locales/bs.yml index 0ecee2efe38..52122847f18 100644 --- a/config/locales/bs.yml +++ b/config/locales/bs.yml @@ -1474,3 +1474,4 @@ bs: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 909f366ada9..c290e015aa0 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -1474,3 +1474,4 @@ ca: text_select_apply_issue_status: Marca l'estat de la incidència field_name_or_email_or_login: Nom, correu o login label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 9a4644217ed..d455911a7cf 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1469,3 +1469,4 @@ cs: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/da.yml b/config/locales/da.yml index 46d41b21284..76663cb90c2 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -1504,3 +1504,4 @@ da: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/de.yml b/config/locales/de.yml index f85345122ea..4195028eac9 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1452,3 +1452,4 @@ de: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/el.yml b/config/locales/el.yml index 4f6ff42312c..69a39f14028 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -1487,3 +1487,4 @@ el: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index c6aa01a93c1..6d105bf5ac8 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -1488,3 +1488,4 @@ en-GB: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/es-PA.yml b/config/locales/es-PA.yml index 88378215664..a747ea13b0c 100644 --- a/config/locales/es-PA.yml +++ b/config/locales/es-PA.yml @@ -1517,3 +1517,4 @@ es-PA: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/es.yml b/config/locales/es.yml index 841e6d7ac93..b4bb9977de6 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -1553,3 +1553,4 @@ es: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/et.yml b/config/locales/et.yml index f6564157527..5faa21a22cc 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -1492,3 +1492,4 @@ et: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/eu.yml b/config/locales/eu.yml index f14c61b944a..da6f5f5224f 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -1488,3 +1488,4 @@ eu: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/fa.yml b/config/locales/fa.yml index e88a1d4895c..b1e61e175a6 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -1421,3 +1421,4 @@ fa: text_select_apply_issue_status: وضعیت مسئله را انتخاب کنید field_name_or_email_or_login: نام، رایانامه یا شناسه کاربری text_default_active_job_queue_changed: آداپتور پیش‌فرض صف که به شکل مناسبی کار می‌کند تنها برای توسعه/آزمون تغییر کرد + label_issue_attachment_added: Attachment added diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 4fcdb99fd75..05d579317d9 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -1508,3 +1508,4 @@ fi: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 9442741fab2..4f2d5c87028 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1467,3 +1467,4 @@ fr: field_name_or_email_or_login: Nom, email ou login text_default_active_job_queue_changed: Gestionnaire de file par défaut le plus adapté label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/gl.yml b/config/locales/gl.yml index b7a177ddcfa..6c5df3537ce 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -1492,3 +1492,4 @@ gl: field_name_or_email_or_login: Nome, correo electrónico ou usuario text_default_active_job_queue_changed: Cambiado o adaptador do sistema de colas por defecto dado que só está pensado para desenvolvemento/probas label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/he.yml b/config/locales/he.yml index fddd4761f84..be0d3ebc1ff 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -1492,3 +1492,4 @@ he: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/hr.yml b/config/locales/hr.yml index 8fbb4a464a5..24f89b440e0 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -1484,3 +1484,4 @@ hr: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/hu.yml b/config/locales/hu.yml index aa33d6f09db..69dd228f9e6 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -1479,3 +1479,4 @@ text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/id.yml b/config/locales/id.yml index 7cc5ff6f635..983f31ebfad 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -1489,3 +1489,4 @@ id: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/it.yml b/config/locales/it.yml index b9e9aa5f65e..78d3ecb751e 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -1480,3 +1480,4 @@ it: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 17faf448ced..1e839709fed 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1439,3 +1439,4 @@ ja: field_name_or_email_or_login: 姓名・メールアドレス・ログインID text_default_active_job_queue_changed: キューアダプターがデフォルト (開発・テスト用) 以外のものに変更済み label_option_auto_lang: 自動設定 + label_issue_attachment_added: Attachment added diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 2e726ef652d..7248fa18336 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -1508,3 +1508,4 @@ ko: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/lt.yml b/config/locales/lt.yml index f18910418ee..3be338cb823 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -1448,3 +1448,4 @@ lt: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/lv.yml b/config/locales/lv.yml index da382c0c116..48a13fde344 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -1481,3 +1481,4 @@ lv: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/mk.yml b/config/locales/mk.yml index a2b86c689b6..a4ab6b50788 100644 --- a/config/locales/mk.yml +++ b/config/locales/mk.yml @@ -1487,3 +1487,4 @@ mk: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/mn.yml b/config/locales/mn.yml index 2c01699c247..7bdc6f42820 100644 --- a/config/locales/mn.yml +++ b/config/locales/mn.yml @@ -1487,3 +1487,4 @@ mn: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/nl.yml b/config/locales/nl.yml index d95e1a679c4..bdee5f421ed 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -1462,3 +1462,4 @@ nl: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/no.yml b/config/locales/no.yml index f1220ffaf0a..e0a6bf98db7 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -1477,3 +1477,4 @@ text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 7f862c2e91a..f19e47b5c5f 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -1431,3 +1431,4 @@ pl: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 529b2d97603..93d5fad0142 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -1492,3 +1492,4 @@ pt-BR: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 2880785880c..94b9897a8a8 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -1480,3 +1480,4 @@ pt: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/ro.yml b/config/locales/ro.yml index 8b7e0b0495a..fe4dfc4a439 100644 --- a/config/locales/ro.yml +++ b/config/locales/ro.yml @@ -1482,3 +1482,4 @@ ro: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 1d64b6f679f..a17a47a9605 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -1557,3 +1557,4 @@ ru: field_name_or_email_or_login: Имя, email или логин text_default_active_job_queue_changed: Изменен адаптер очереди по умолчанию, который хорошо подходит только для разработки/тестирования label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 2941cbcdce0..4420280defd 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -1476,3 +1476,4 @@ sk: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 79d7c0c3009..c8b4828615b 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -1487,3 +1487,4 @@ sl: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 3b835c66bd0..36032478e3a 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -1449,3 +1449,4 @@ sq: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/sr-YU.yml b/config/locales/sr-YU.yml index 153e63fec34..5637d4daf92 100644 --- a/config/locales/sr-YU.yml +++ b/config/locales/sr-YU.yml @@ -1489,3 +1489,4 @@ sr-YU: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 74d3a87dd48..4e19f13d12b 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -1488,3 +1488,4 @@ sr: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 5b48d655a52..64ee13e9647 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -1520,3 +1520,4 @@ sv: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/ta-IN.yml b/config/locales/ta-IN.yml index 4f05d823a3a..226b09732da 100644 --- a/config/locales/ta-IN.yml +++ b/config/locales/ta-IN.yml @@ -1443,3 +1443,4 @@ ta-IN: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/th.yml b/config/locales/th.yml index b571dbb801d..be484b6a41e 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -1483,3 +1483,4 @@ th: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/tr.yml b/config/locales/tr.yml index f9a0d35c644..8074cc014d4 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -1486,3 +1486,4 @@ tr: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/uk.yml b/config/locales/uk.yml index fc28f90b0ae..1fe1d2d5273 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -1475,3 +1475,4 @@ uk: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 498553a93d1..d4f75d0a205 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -1492,3 +1492,4 @@ vi: text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed label_option_auto_lang: auto + label_issue_attachment_added: Attachment added diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index f34f0b4c2c5..2f0fb57406f 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -1504,3 +1504,4 @@ field_name_or_email_or_login: 姓名, 電子郵件或帳戶名稱 text_default_active_job_queue_changed: 已變更僅適用於開發/測試環境的佇列適配器 (queue adapter) label_option_auto_lang: 自動選取語言 + label_issue_attachment_added: Attachment added diff --git a/config/locales/zh.yml b/config/locales/zh.yml index d9bcce57d65..6dd150f04ff 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -1423,3 +1423,4 @@ zh: field_name_or_email_or_login: 姓名、电子邮件或登录名 text_default_active_job_queue_changed: 仅适用于开发/测试环境的默认队列适配器已改变 label_option_auto_lang: auto + label_issue_attachment_added: Attachment added From 8b57ffc3c750b253e316fbfd8871d5c2da045557 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Fri, 3 May 2024 13:14:18 +0000 Subject: [PATCH 010/459] Adds the date of the last activity to the list of available columns for Projects (#23954). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Frederico Camara (@fredsdc) and Marius BĂLTEANU (@marius.balteanu). git-svn-id: https://svn.redmine.org/redmine/trunk@22811 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/admin_controller.rb | 5 ++--- app/controllers/projects_controller.rb | 15 +++++++------- app/models/project.rb | 20 +++++++++++++++++++ app/models/project_query.rb | 17 ++++++++++++++-- config/locales/en.yml | 1 + config/locales/pt-BR.yml | 1 + .../lib/acts_as_activity_provider.rb | 9 ++++++--- lib/redmine/activity/fetcher.rb | 11 +++++++--- test/functional/projects_controller_test.rb | 12 +++++++++++ test/unit/project_test.rb | 7 +++++++ 10 files changed, 79 insertions(+), 19 deletions(-) diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index 7fcb6ac5d5d..7e36d52939c 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -38,11 +38,10 @@ def index def projects retrieve_query(ProjectQuery, false, :defaults => @default_columns_names) @query.admin_projects = 1 - scope = @query.results_scope - @entry_count = scope.count + @entry_count = @query.result_count @entry_pages = Paginator.new @entry_count, per_page_option, params['page'] - @projects = scope.limit(@entry_pages.per_page).offset(@entry_pages.offset).to_a + @projects = @query.results_scope(:limit => @entry_pages.per_page, :offset => @entry_pages.offset).to_a render :action => "projects", :layout => false if request.xhr? end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 66d54db38f1..91616d619bb 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -53,31 +53,30 @@ def index retrieve_default_query retrieve_project_query - scope = project_scope respond_to do |format| format.html do # TODO: see what to do with the board view and pagination if @query.display_type == 'board' - @entries = scope.to_a + @entries = project_scope.to_a else - @entry_count = scope.count + @entry_count = @query.result_count @entry_pages = Paginator.new @entry_count, per_page_option, params['page'] - @entries = scope.offset(@entry_pages.offset).limit(@entry_pages.per_page).to_a + @entries = project_scope(:offset => @entry_pages.offset, :limit => @entry_pages.per_page).to_a end end format.api do @offset, @limit = api_offset_and_limit - @project_count = scope.count - @projects = scope.offset(@offset).limit(@limit).to_a + @project_count = @query.result_count + @projects = project_scope(:offset => @offset, :limit => @limit) end format.atom do - projects = scope.reorder(:created_on => :desc).limit(Setting.feeds_limit.to_i).to_a + projects = project_scope(:order => {:created_on => :desc}, :limit => Setting.feeds_limit.to_i).to_a render_feed(projects, :title => "#{Setting.app_title}: #{l(:label_project_latest)}") end format.csv do # Export all entries - entries = scope.to_a + entries = project_scope.to_a send_data(query_to_csv(entries, @query, params), :type => 'text/csv; header=present', :filename => 'projects.csv') end end diff --git a/app/models/project.rb b/app/models/project.rb index f9000829b9c..abac2a1f0d2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -379,6 +379,7 @@ def reload(*args) @due_date = nil @override_members = nil @assignable_users = nil + @last_activity_date = nil base_reload(*args) end @@ -1005,6 +1006,20 @@ def visible_custom_field_values(user = nil) end end + def last_activity_date + @last_activity_date || fetch_last_activity_date + end + + # Preloads last activity date for a collection of projects + def self.load_last_activity_date(projects, user=User.current) + if projects.any? + last_activities = Redmine::Activity::Fetcher.new(User.current).events(nil, nil, :last_by_project => true).to_h + projects.each do |project| + project.instance_variable_set(:@last_activity_date, last_activities[project.id]) + end + end + end + private def update_inherited_members @@ -1312,4 +1327,9 @@ def archive! end update_attribute :status, STATUS_ARCHIVED end + + def fetch_last_activity_date + latest_activities = Redmine::Activity::Fetcher.new(User.current, :project => self).events(nil, nil, :last_by_project => true) + latest_activities.empty? ? nil : latest_activities.to_h[self.id] + end end diff --git a/app/models/project_query.rb b/app/models/project_query.rb index 113287ed806..dde3e9cc1f3 100644 --- a/app/models/project_query.rb +++ b/app/models/project_query.rb @@ -36,7 +36,8 @@ class ProjectQuery < Query QueryColumn.new(:identifier, :sortable => "#{Project.table_name}.identifier"), QueryColumn.new(:parent_id, :sortable => "#{Project.table_name}.lft ASC", :default_order => 'desc', :caption => :field_parent), QueryColumn.new(:is_public, :sortable => "#{Project.table_name}.is_public", :groupable => true), - QueryColumn.new(:created_on, :sortable => "#{Project.table_name}.created_on", :default_order => 'desc') + QueryColumn.new(:created_on, :sortable => "#{Project.table_name}.created_on", :default_order => 'desc'), + QueryColumn.new(:last_activity_date) ] def self.default(project: nil, user: User.current) @@ -140,6 +141,13 @@ def base_scope end end + # Returns the project count + def result_count + base_scope.count + rescue ::ActiveRecord::StatementInvalid => e + raise StatementInvalid, e.message + end + def results_scope(options={}) order_option = [group_by_sort_order, (options[:order] || sort_clause)].flatten.reject(&:blank?) @@ -156,6 +164,11 @@ def results_scope(options={}) scope = scope.preload(:parent) end - scope + projects = scope.to_a + if has_column?(:last_activity_date) + Project.load_last_activity_date(scope) + end + + projects end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 3ae06f745f8..c842e4d7b9b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -419,6 +419,7 @@ en: field_default_time_entry_activity: Default spent time activity field_any_searchable: Any searchable text field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity setting_app_title: Application title setting_welcome_text: Welcome text diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 93d5fad0142..0a422ce86a7 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -299,6 +299,7 @@ pt-BR: field_default_value: Padrão field_comments_sorting: Visualizar comentários field_parent_title: Página pai + field_last_activity_date: Última atividade setting_app_title: Título da aplicação setting_welcome_text: Texto de boas-vindas diff --git a/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb b/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb index 5954d501dbd..ac334c19a50 100644 --- a/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb +++ b/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb @@ -64,9 +64,8 @@ def find_events(event_type, user, from, to, options) ActiveSupport::Deprecation.warn "acts_as_activity_provider with implicit :scope option is deprecated. Please pass a scope on the #{self.name} as a proc." end - if from && to - scope = scope.where("#{provider_options[:timestamp]} BETWEEN ? AND ?", from, to) - end + scope = scope.where("#{provider_options[:timestamp]} >= ?", from) if from + scope = scope.where("#{provider_options[:timestamp]} <= ?", to) if to if options[:author] return [] if provider_options[:author_key].nil? @@ -87,6 +86,10 @@ def find_events(event_type, user, from, to, options) scope = scope.where(Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym, options)) end + if options[:last_by_project] + scope = scope.group("#{Project.table_name}.id").maximum(provider_options[:timestamp]) + end + scope.to_a end end diff --git a/lib/redmine/activity/fetcher.rb b/lib/redmine/activity/fetcher.rb index cbd20425d2e..4264c2e5d77 100644 --- a/lib/redmine/activity/fetcher.rb +++ b/lib/redmine/activity/fetcher.rb @@ -87,6 +87,7 @@ def default_scope! def events(from = nil, to = nil, options={}) e = [] @options[:limit] = options[:limit] + @options[:last_by_project] = options[:last_by_project] if options[:last_by_project] @scope.each do |event_type| constantized_providers(event_type).each do |provider| @@ -94,10 +95,14 @@ def events(from = nil, to = nil, options={}) end end - e.sort! {|a, b| b.event_datetime <=> a.event_datetime} + if options[:last_by_project] + e.sort! + else + e.sort! {|a, b| b.event_datetime <=> a.event_datetime} - if options[:limit] - e = e.slice(0, options[:limit]) + if options[:limit] + e = e.slice(0, options[:limit]) + end end e end diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index a2356185bfd..d1de3b631ca 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -252,6 +252,18 @@ def test_index_with_int_custom_field_total assert_select ".total-for-cf-#{field.id} span.value", :text => '9' end + def test_index_with_last_activity_date_column + with_settings :project_list_defaults => {'column_names' => %w(name short_description last_activity_date)} do + get :index, :params => { + :display_type => 'list' + } + assert_response :success + end + assert_equal ['Name', 'Description', 'Last activity'], columns_in_list + assert_select 'tr#project-1 td.last_activity_date', :text => format_time(Journal.find(3).created_on) + assert_select 'tr#project-4 td.last_activity_date', :text => '' + end + def test_index_should_retrieve_default_query query = ProjectQuery.find(11) ProjectQuery.stubs(:default).returns query diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb index eacbf0c92e9..a7047d71c0f 100644 --- a/test/unit/project_test.rb +++ b/test/unit/project_test.rb @@ -1161,4 +1161,11 @@ def test_like_scope_should_escape_query r = Project.like('eco_k') assert_include project, r end + + def test_last_activity_date + # Note with id 3 is the last activity on Project 1 + assert_equal Journal.find(3).created_on, Project.find(1).last_activity_date + # Project without activity should return nil + assert_nil Project.find(4).last_activity_date + end end From 17aeeb705937730b03e2c612d59c942ce3dc2656 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Fri, 3 May 2024 13:20:18 +0000 Subject: [PATCH 011/459] Update locales (#37862). git-svn-id: https://svn.redmine.org/redmine/trunk@22812 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/ar.yml | 1 + config/locales/az.yml | 1 + config/locales/bg.yml | 1 + config/locales/bs.yml | 1 + config/locales/ca.yml | 1 + config/locales/cs.yml | 1 + config/locales/da.yml | 1 + config/locales/el.yml | 1 + config/locales/en-GB.yml | 1 + config/locales/es-PA.yml | 1 + config/locales/es.yml | 1 + config/locales/et.yml | 1 + config/locales/eu.yml | 1 + config/locales/fa.yml | 1 + config/locales/fi.yml | 1 + config/locales/fr.yml | 1 + config/locales/gl.yml | 1 + config/locales/he.yml | 1 + config/locales/hr.yml | 1 + config/locales/hu.yml | 1 + config/locales/id.yml | 1 + config/locales/it.yml | 1 + config/locales/ja.yml | 1 + config/locales/ko.yml | 1 + config/locales/lt.yml | 1 + config/locales/lv.yml | 1 + config/locales/mk.yml | 1 + config/locales/mn.yml | 1 + config/locales/nl.yml | 1 + config/locales/no.yml | 1 + config/locales/pl.yml | 1 + config/locales/pt-BR.yml | 1 + config/locales/pt.yml | 1 + config/locales/ro.yml | 1 + config/locales/ru.yml | 1 + config/locales/sk.yml | 1 + config/locales/sl.yml | 1 + config/locales/sq.yml | 1 + config/locales/sr-YU.yml | 1 + config/locales/sr.yml | 1 + config/locales/sv.yml | 1 + config/locales/ta-IN.yml | 1 + config/locales/th.yml | 1 + config/locales/tr.yml | 1 + config/locales/uk.yml | 1 + config/locales/vi.yml | 1 + config/locales/zh-TW.yml | 1 + config/locales/zh.yml | 1 + 48 files changed, 48 insertions(+) diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 4171ff62e0f..ff9a7e34761 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -1488,3 +1488,4 @@ ar: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/az.yml b/config/locales/az.yml index 904b44c0503..bc0dfb4cb9e 100644 --- a/config/locales/az.yml +++ b/config/locales/az.yml @@ -1580,3 +1580,4 @@ az: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/bg.yml b/config/locales/bg.yml index e3f54f094e3..10290f10e55 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -1433,3 +1433,4 @@ bg: field_name_or_email_or_login: Име, e-mail или login име label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/bs.yml b/config/locales/bs.yml index 52122847f18..a0c6444e43a 100644 --- a/config/locales/bs.yml +++ b/config/locales/bs.yml @@ -1475,3 +1475,4 @@ bs: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/ca.yml b/config/locales/ca.yml index c290e015aa0..ee7eccbac35 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -1475,3 +1475,4 @@ ca: field_name_or_email_or_login: Nom, correu o login label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/cs.yml b/config/locales/cs.yml index d455911a7cf..08793ac7c6a 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1470,3 +1470,4 @@ cs: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/da.yml b/config/locales/da.yml index 76663cb90c2..b74fac11da3 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -1505,3 +1505,4 @@ da: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/el.yml b/config/locales/el.yml index 69a39f14028..37de3720dc5 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -1488,3 +1488,4 @@ el: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 6d105bf5ac8..f7b70b50bd7 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -1489,3 +1489,4 @@ en-GB: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/es-PA.yml b/config/locales/es-PA.yml index a747ea13b0c..665629f4fdb 100644 --- a/config/locales/es-PA.yml +++ b/config/locales/es-PA.yml @@ -1518,3 +1518,4 @@ es-PA: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/es.yml b/config/locales/es.yml index b4bb9977de6..b44df7cb32f 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -1554,3 +1554,4 @@ es: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/et.yml b/config/locales/et.yml index 5faa21a22cc..51f70570f1b 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -1493,3 +1493,4 @@ et: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/eu.yml b/config/locales/eu.yml index da6f5f5224f..a5342b626ff 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -1489,3 +1489,4 @@ eu: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/fa.yml b/config/locales/fa.yml index b1e61e175a6..1e79e3539e5 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -1422,3 +1422,4 @@ fa: field_name_or_email_or_login: نام، رایانامه یا شناسه کاربری text_default_active_job_queue_changed: آداپتور پیش‌فرض صف که به شکل مناسبی کار می‌کند تنها برای توسعه/آزمون تغییر کرد label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 05d579317d9..e011b433759 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -1509,3 +1509,4 @@ fi: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 4f2d5c87028..f53c703c419 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1468,3 +1468,4 @@ fr: text_default_active_job_queue_changed: Gestionnaire de file par défaut le plus adapté label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/gl.yml b/config/locales/gl.yml index 6c5df3537ce..7e1a764af71 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -1493,3 +1493,4 @@ gl: text_default_active_job_queue_changed: Cambiado o adaptador do sistema de colas por defecto dado que só está pensado para desenvolvemento/probas label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/he.yml b/config/locales/he.yml index be0d3ebc1ff..af2184534aa 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -1493,3 +1493,4 @@ he: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/hr.yml b/config/locales/hr.yml index 24f89b440e0..c63a0c59f02 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -1485,3 +1485,4 @@ hr: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 69dd228f9e6..5c820309319 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -1480,3 +1480,4 @@ only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/id.yml b/config/locales/id.yml index 983f31ebfad..0ca603c7919 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -1490,3 +1490,4 @@ id: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/it.yml b/config/locales/it.yml index 78d3ecb751e..496a7def877 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -1481,3 +1481,4 @@ it: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 1e839709fed..72571a6d176 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1440,3 +1440,4 @@ ja: text_default_active_job_queue_changed: キューアダプターがデフォルト (開発・テスト用) 以外のものに変更済み label_option_auto_lang: 自動設定 label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 7248fa18336..9c5d9801f00 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -1509,3 +1509,4 @@ ko: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/lt.yml b/config/locales/lt.yml index 3be338cb823..b43058bace6 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -1449,3 +1449,4 @@ lt: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 48a13fde344..42b6b9b8e52 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -1482,3 +1482,4 @@ lv: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/mk.yml b/config/locales/mk.yml index a4ab6b50788..952c5e17f22 100644 --- a/config/locales/mk.yml +++ b/config/locales/mk.yml @@ -1488,3 +1488,4 @@ mk: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/mn.yml b/config/locales/mn.yml index 7bdc6f42820..08670f5852c 100644 --- a/config/locales/mn.yml +++ b/config/locales/mn.yml @@ -1488,3 +1488,4 @@ mn: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/nl.yml b/config/locales/nl.yml index bdee5f421ed..6e3361d3ec7 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -1463,3 +1463,4 @@ nl: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/no.yml b/config/locales/no.yml index e0a6bf98db7..a8a317cf300 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -1478,3 +1478,4 @@ only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/pl.yml b/config/locales/pl.yml index f19e47b5c5f..5e666a28791 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -1432,3 +1432,4 @@ pl: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 0a422ce86a7..4c58d757898 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -1494,3 +1494,4 @@ pt-BR: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 94b9897a8a8..2de2e8bba9d 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -1481,3 +1481,4 @@ pt: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/ro.yml b/config/locales/ro.yml index fe4dfc4a439..9f5398a6a55 100644 --- a/config/locales/ro.yml +++ b/config/locales/ro.yml @@ -1483,3 +1483,4 @@ ro: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/ru.yml b/config/locales/ru.yml index a17a47a9605..cd97306c8b7 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -1558,3 +1558,4 @@ ru: text_default_active_job_queue_changed: Изменен адаптер очереди по умолчанию, который хорошо подходит только для разработки/тестирования label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 4420280defd..50de2074bff 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -1477,3 +1477,4 @@ sk: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/sl.yml b/config/locales/sl.yml index c8b4828615b..175c1971fe8 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -1488,3 +1488,4 @@ sl: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 36032478e3a..462ced05028 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -1450,3 +1450,4 @@ sq: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/sr-YU.yml b/config/locales/sr-YU.yml index 5637d4daf92..20ec9134243 100644 --- a/config/locales/sr-YU.yml +++ b/config/locales/sr-YU.yml @@ -1490,3 +1490,4 @@ sr-YU: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 4e19f13d12b..2fd54f87b10 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -1489,3 +1489,4 @@ sr: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 64ee13e9647..767689f39ce 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -1521,3 +1521,4 @@ sv: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/ta-IN.yml b/config/locales/ta-IN.yml index 226b09732da..d14a2ba72df 100644 --- a/config/locales/ta-IN.yml +++ b/config/locales/ta-IN.yml @@ -1444,3 +1444,4 @@ ta-IN: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/th.yml b/config/locales/th.yml index be484b6a41e..d26f9f9ca82 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -1484,3 +1484,4 @@ th: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 8074cc014d4..5020ae231df 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -1487,3 +1487,4 @@ tr: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 1fe1d2d5273..79bbf9df952 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -1476,3 +1476,4 @@ uk: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/vi.yml b/config/locales/vi.yml index d4f75d0a205..871ab49d48f 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -1493,3 +1493,4 @@ vi: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 2f0fb57406f..b80aec636da 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -1505,3 +1505,4 @@ text_default_active_job_queue_changed: 已變更僅適用於開發/測試環境的佇列適配器 (queue adapter) label_option_auto_lang: 自動選取語言 label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 6dd150f04ff..bacc6159393 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -1424,3 +1424,4 @@ zh: text_default_active_job_queue_changed: 仅适用于开发/测试环境的默认队列适配器已改变 label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_estimated_remaining_hours: Estimated remaining time From 1ba9e5af04e5a95d67e7f22886fe080e5bdeb7ce Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Sat, 4 May 2024 08:04:33 +0000 Subject: [PATCH 012/459] Add workflow to run Rubocop action. git-svn-id: https://svn.redmine.org/redmine/trunk@22813 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .github/workflows/rubyonrails.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/rubyonrails.yml diff --git a/.github/workflows/rubyonrails.yml b/.github/workflows/rubyonrails.yml new file mode 100644 index 00000000000..07882bdc87c --- /dev/null +++ b/.github/workflows/rubyonrails.yml @@ -0,0 +1,17 @@ +name: "Ruby on Rails CI" +on: + push: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Install Ruby and gems + uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0 + with: + ruby-version: 3.2 + bundler-cache: true + - name: Lint Ruby files + run: bundle exec rubocop --parallel From 306ecf382bf24ddaac2971e200acda702d4a9cb4 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Mon, 6 May 2024 20:05:28 +0000 Subject: [PATCH 013/459] Updates list of excluded files for Rubocop "Rails/BulkChangeTable" offense. git-svn-id: https://svn.redmine.org/redmine/trunk@22814 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .rubocop.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.rubocop.yml b/.rubocop.yml index 4b9e50d642c..1873eefdcea 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -137,6 +137,9 @@ Rails/BulkChangeTable: Exclude: - 'db/migrate/20120714122200_add_workflows_rule_fields.rb' - 'db/migrate/20131214094309_remove_custom_fields_min_max_length_default_values.rb' + - 'db/migrate/20190510070108_add_unique_id_to_import_items.rb' + - 'db/migrate/20200826153402_add_totp_to_user.rb' + - 'db/migrate/20221012135202_add_index_to_custom_values.rb' Rails/CompactBlank: Enabled: false From 9ef1cdd375793b05d9ef7a6036678168f2704750 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Mon, 6 May 2024 20:28:31 +0000 Subject: [PATCH 014/459] Updates list of excluded files for Rubocop "Rails/BulkChangeTable" offense. git-svn-id: https://svn.redmine.org/redmine/trunk@22815 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .rubocop.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.rubocop.yml b/.rubocop.yml index 1873eefdcea..52c4db3f5f4 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -136,6 +136,7 @@ Rails/ApplicationRecord: Rails/BulkChangeTable: Exclude: - 'db/migrate/20120714122200_add_workflows_rule_fields.rb' + - 'db/migrate/20130217094251_remove_issues_default_fk_values.rb' - 'db/migrate/20131214094309_remove_custom_fields_min_max_length_default_values.rb' - 'db/migrate/20190510070108_add_unique_id_to_import_items.rb' - 'db/migrate/20200826153402_add_totp_to_user.rb' From b4bfb6b581035b52a193c74ac74825f3652a014a Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Tue, 7 May 2024 18:36:46 +0000 Subject: [PATCH 015/459] Replaces use of Digest::MD5 / Digest::SHA1 with ActiveSupport::Digest (#35217). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Jens Krämer (@jkraemer). git-svn-id: https://svn.redmine.org/redmine/trunk@22816 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/repositories_controller.rb | 2 +- app/models/attachment.rb | 4 ++-- app/views/repositories/_dir_list_content.html.erb | 2 +- lib/redmine/wiki_formatting.rb | 3 +-- lib/redmine/wiki_formatting/section_helper.rb | 4 ++-- lib/redmine/wiki_formatting/textile/formatter.rb | 2 -- test/functional/wiki_controller_test.rb | 2 +- .../redmine/wiki_formatting/common_mark/formatter_test.rb | 2 +- .../lib/redmine/wiki_formatting/markdown_formatter_test.rb | 2 +- .../lib/redmine/wiki_formatting/textile_formatter_test.rb | 7 +++---- 10 files changed, 13 insertions(+), 17 deletions(-) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 2645ded4079..8deb3540468 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -279,7 +279,7 @@ def diff User.current.preference.save end @cache_key = "repositories/diff/#{@repository.id}/" + - Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}") + ActiveSupport::Digest.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}") unless read_fragment(@cache_key) @diff = @repository.diff(@path, @rev, @rev_to) (show_error_not_found; return) unless @diff diff --git a/app/models/attachment.rb b/app/models/attachment.rb index c9054e90327..59addf5281c 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -135,7 +135,7 @@ def filename=(arg) end # Copies the temporary file to its final location - # and computes its MD5 hash + # and computes its hash def files_to_final_location if @temp_file self.disk_directory = target_directory @@ -559,7 +559,7 @@ def create_diskfile(filename, directory=nil, &block) if %r{^[a-zA-Z0-9_\.\-]*$}.match?(filename) && filename.length <= 50 ascii = filename else - ascii = Digest::MD5.hexdigest(filename) + ascii = ActiveSupport::Digest.hexdigest(filename) # keep the extension if any ascii << $1 if filename =~ %r{(\.[a-zA-Z0-9]+)$} end diff --git a/app/views/repositories/_dir_list_content.html.erb b/app/views/repositories/_dir_list_content.html.erb index ee68c1b7a5d..396c7f6d0ff 100644 --- a/app/views/repositories/_dir_list_content.html.erb +++ b/app/views/repositories/_dir_list_content.html.erb @@ -1,5 +1,5 @@ <% @entries.each do |entry| %> -<% tr_id = Digest::MD5.hexdigest(entry.path) +<% tr_id = ActiveSupport::Digest.hexdigest(entry.path) depth = params[:depth].to_i %> <% ent_path = Redmine::CodesetUtil.replace_invalid_utf8(entry.path) %> <% ent_name = Redmine::CodesetUtil.replace_invalid_utf8(entry.name) %> diff --git a/lib/redmine/wiki_formatting.rb b/lib/redmine/wiki_formatting.rb index 3486c74c615..cc68e9972ba 100644 --- a/lib/redmine/wiki_formatting.rb +++ b/lib/redmine/wiki_formatting.rb @@ -18,7 +18,6 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require_relative 'wiki_formatting/textile/redcloth3' -require 'digest/md5' module Redmine module WikiFormatting @@ -110,7 +109,7 @@ def supports_section_edit? # Returns a cache key for the given text +format+, +text+, +object+ and +attribute+ or nil if no caching should be done def cache_key_for(format, text, object, attribute) if object && attribute && !object.new_record? && format.present? - "formatted_text/#{format}/#{object.class.model_name.cache_key}/#{object.id}-#{attribute}-#{Digest::MD5.hexdigest text}" + "formatted_text/#{format}/#{object.class.model_name.cache_key}/#{object.id}-#{attribute}-#{ActiveSupport::Digest.hexdigest text}" end end diff --git a/lib/redmine/wiki_formatting/section_helper.rb b/lib/redmine/wiki_formatting/section_helper.rb index 9221d990df7..6f53a3f8e7f 100644 --- a/lib/redmine/wiki_formatting/section_helper.rb +++ b/lib/redmine/wiki_formatting/section_helper.rb @@ -22,13 +22,13 @@ module WikiFormatting module SectionHelper def get_section(index) section = extract_sections(index)[1] - hash = Digest::MD5.hexdigest(section) + hash = ActiveSupport::Digest.hexdigest(section) return section, hash end def update_section(index, update, hash=nil) t = extract_sections(index) - if hash.present? && hash != Digest::MD5.hexdigest(t[1]) + if hash.present? && hash != ActiveSupport::Digest.hexdigest(t[1]) raise Redmine::WikiFormatting::StaleSectionError end diff --git a/lib/redmine/wiki_formatting/textile/formatter.rb b/lib/redmine/wiki_formatting/textile/formatter.rb index 1cacfeed61c..35684a6c78c 100644 --- a/lib/redmine/wiki_formatting/textile/formatter.rb +++ b/lib/redmine/wiki_formatting/textile/formatter.rb @@ -17,8 +17,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -require 'digest/md5' - module Redmine module WikiFormatting module Textile diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb index 215c9caf4f3..31dcf395d5c 100644 --- a/test/functional/wiki_controller_test.rb +++ b/test/functional/wiki_controller_test.rb @@ -677,7 +677,7 @@ def test_update_section_should_not_allow_stale_section_update :version => 3 }, :section => 2, - :section_hash => Digest::MD5.hexdigest("wrong hash") + :section_hash => ActiveSupport::Digest.hexdigest("wrong hash") } end end diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb index 16bd8c97296..03376e34219 100644 --- a/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb +++ b/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb @@ -292,7 +292,7 @@ def assert_section_with_hash(expected, text, index) assert_kind_of Array, result assert_equal 2, result.size assert_equal expected, result.first, "section content did not match" - assert_equal Digest::MD5.hexdigest(expected), result.last, "section hash did not match" + assert_equal ActiveSupport::Digest.hexdigest(expected), result.last, "section hash did not match" end end end diff --git a/test/unit/lib/redmine/wiki_formatting/markdown_formatter_test.rb b/test/unit/lib/redmine/wiki_formatting/markdown_formatter_test.rb index 75d3ff3659c..012ec7ec92e 100644 --- a/test/unit/lib/redmine/wiki_formatting/markdown_formatter_test.rb +++ b/test/unit/lib/redmine/wiki_formatting/markdown_formatter_test.rb @@ -349,6 +349,6 @@ def assert_section_with_hash(expected, text, index) assert_kind_of Array, result assert_equal 2, result.size assert_equal expected, result.first, "section content did not match" - assert_equal Digest::MD5.hexdigest(expected), result.last, "section hash did not match" + assert_equal ActiveSupport::Digest.hexdigest(expected), result.last, "section hash did not match" end end diff --git a/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb b/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb index cdbad2a552e..32280cfdf05 100644 --- a/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb +++ b/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb @@ -19,7 +19,6 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require_relative '../../../../test_helper' -require 'digest/md5' class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase def setup @@ -491,13 +490,13 @@ def test_update_section_with_hash_should_update_the_requested_section assert_equal( [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE). - update_section(2, replacement, Digest::MD5.hexdigest(STR_WITHOUT_PRE[1])) + update_section(2, replacement, ActiveSupport::Digest.hexdigest(STR_WITHOUT_PRE[1])) ) end def test_update_section_with_wrong_hash_should_raise_an_error assert_raise Redmine::WikiFormatting::StaleSectionError do - @formatter.new(TEXT_WITHOUT_PRE).update_section(2, "New text", Digest::MD5.hexdigest("Old text")) + @formatter.new(TEXT_WITHOUT_PRE).update_section(2, "New text", ActiveSupport::Digest.hexdigest("Old text")) end end @@ -809,6 +808,6 @@ def assert_section_with_hash(expected, text, index) assert_kind_of Array, result assert_equal 2, result.size assert_equal expected, result.first, "section content did not match" - assert_equal Digest::MD5.hexdigest(expected), result.last, "section hash did not match" + assert_equal ActiveSupport::Digest.hexdigest(expected), result.last, "section hash did not match" end end From 1e3c860315c0bf97f1e642361464e854e8bea3f4 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Sat, 11 May 2024 08:00:17 +0000 Subject: [PATCH 016/459] Update locales (#23954). git-svn-id: https://svn.redmine.org/redmine/trunk@22817 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/ar.yml | 1 + config/locales/az.yml | 1 + config/locales/bg.yml | 1 + config/locales/bs.yml | 1 + config/locales/ca.yml | 1 + config/locales/cs.yml | 1 + config/locales/da.yml | 1 + config/locales/de.yml | 1 + config/locales/el.yml | 1 + config/locales/en-GB.yml | 1 + config/locales/es-PA.yml | 1 + config/locales/es.yml | 1 + config/locales/et.yml | 1 + config/locales/eu.yml | 1 + config/locales/fa.yml | 1 + config/locales/fi.yml | 1 + config/locales/fr.yml | 1 + config/locales/gl.yml | 1 + config/locales/he.yml | 1 + config/locales/hr.yml | 1 + config/locales/hu.yml | 1 + config/locales/id.yml | 1 + config/locales/it.yml | 1 + config/locales/ja.yml | 1 + config/locales/ko.yml | 1 + config/locales/lt.yml | 1 + config/locales/lv.yml | 1 + config/locales/mk.yml | 1 + config/locales/mn.yml | 1 + config/locales/nl.yml | 1 + config/locales/no.yml | 1 + config/locales/pl.yml | 1 + config/locales/pt.yml | 1 + config/locales/ro.yml | 1 + config/locales/ru.yml | 1 + config/locales/sk.yml | 1 + config/locales/sl.yml | 1 + config/locales/sq.yml | 1 + config/locales/sr-YU.yml | 1 + config/locales/sr.yml | 1 + config/locales/sv.yml | 1 + config/locales/ta-IN.yml | 1 + config/locales/th.yml | 1 + config/locales/tr.yml | 1 + config/locales/uk.yml | 1 + config/locales/vi.yml | 1 + config/locales/zh-TW.yml | 1 + config/locales/zh.yml | 1 + 48 files changed, 48 insertions(+) diff --git a/config/locales/ar.yml b/config/locales/ar.yml index ff9a7e34761..92de6e92bbf 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -1489,3 +1489,4 @@ ar: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/az.yml b/config/locales/az.yml index bc0dfb4cb9e..a3b5d661a0f 100644 --- a/config/locales/az.yml +++ b/config/locales/az.yml @@ -1581,3 +1581,4 @@ az: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 10290f10e55..0108729a611 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -1434,3 +1434,4 @@ bg: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/bs.yml b/config/locales/bs.yml index a0c6444e43a..a281d19b81a 100644 --- a/config/locales/bs.yml +++ b/config/locales/bs.yml @@ -1476,3 +1476,4 @@ bs: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/ca.yml b/config/locales/ca.yml index ee7eccbac35..4739460e550 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -1476,3 +1476,4 @@ ca: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 08793ac7c6a..e172edf0595 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1471,3 +1471,4 @@ cs: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/da.yml b/config/locales/da.yml index b74fac11da3..bdf3882a915 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -1506,3 +1506,4 @@ da: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/de.yml b/config/locales/de.yml index 4195028eac9..c348a64bea6 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1453,3 +1453,4 @@ de: only for dev/test changed label_option_auto_lang: auto label_issue_attachment_added: Attachment added + field_last_activity_date: Last activity diff --git a/config/locales/el.yml b/config/locales/el.yml index 37de3720dc5..10d2673dc0a 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -1489,3 +1489,4 @@ el: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index f7b70b50bd7..c79496dec2e 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -1490,3 +1490,4 @@ en-GB: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/es-PA.yml b/config/locales/es-PA.yml index 665629f4fdb..3e7d287a8c7 100644 --- a/config/locales/es-PA.yml +++ b/config/locales/es-PA.yml @@ -1519,3 +1519,4 @@ es-PA: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/es.yml b/config/locales/es.yml index b44df7cb32f..ba2c644a57d 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -1555,3 +1555,4 @@ es: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/et.yml b/config/locales/et.yml index 51f70570f1b..f05401452b3 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -1494,3 +1494,4 @@ et: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/eu.yml b/config/locales/eu.yml index a5342b626ff..37876fad760 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -1490,3 +1490,4 @@ eu: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/fa.yml b/config/locales/fa.yml index 1e79e3539e5..83cf8c96495 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -1423,3 +1423,4 @@ fa: text_default_active_job_queue_changed: آداپتور پیش‌فرض صف که به شکل مناسبی کار می‌کند تنها برای توسعه/آزمون تغییر کرد label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/fi.yml b/config/locales/fi.yml index e011b433759..3e39ac724e8 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -1510,3 +1510,4 @@ fi: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/fr.yml b/config/locales/fr.yml index f53c703c419..e67931c792d 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1469,3 +1469,4 @@ fr: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/gl.yml b/config/locales/gl.yml index 7e1a764af71..77702e0accd 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -1494,3 +1494,4 @@ gl: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/he.yml b/config/locales/he.yml index af2184534aa..9c19d937ba4 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -1494,3 +1494,4 @@ he: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/hr.yml b/config/locales/hr.yml index c63a0c59f02..19495663a0b 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -1486,3 +1486,4 @@ hr: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 5c820309319..9e8970f6cd6 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -1481,3 +1481,4 @@ label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/id.yml b/config/locales/id.yml index 0ca603c7919..f8074f7a4f9 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -1491,3 +1491,4 @@ id: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/it.yml b/config/locales/it.yml index 496a7def877..296f98465a7 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -1482,3 +1482,4 @@ it: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 72571a6d176..3756b62bea0 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1441,3 +1441,4 @@ ja: label_option_auto_lang: 自動設定 label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 9c5d9801f00..d7b8f14d21d 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -1510,3 +1510,4 @@ ko: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/lt.yml b/config/locales/lt.yml index b43058bace6..8d67ab7f49c 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -1450,3 +1450,4 @@ lt: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 42b6b9b8e52..8b659513990 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -1483,3 +1483,4 @@ lv: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/mk.yml b/config/locales/mk.yml index 952c5e17f22..8bbbcb3df9c 100644 --- a/config/locales/mk.yml +++ b/config/locales/mk.yml @@ -1489,3 +1489,4 @@ mk: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/mn.yml b/config/locales/mn.yml index 08670f5852c..aee221ca19e 100644 --- a/config/locales/mn.yml +++ b/config/locales/mn.yml @@ -1489,3 +1489,4 @@ mn: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 6e3361d3ec7..19872c3e94b 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -1464,3 +1464,4 @@ nl: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/no.yml b/config/locales/no.yml index a8a317cf300..ea08e0e0895 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -1479,3 +1479,4 @@ label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 5e666a28791..a8848923cdb 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -1433,3 +1433,4 @@ pl: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 2de2e8bba9d..4f21e01fd6a 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -1482,3 +1482,4 @@ pt: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/ro.yml b/config/locales/ro.yml index 9f5398a6a55..4bd56f2affc 100644 --- a/config/locales/ro.yml +++ b/config/locales/ro.yml @@ -1484,3 +1484,4 @@ ro: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/ru.yml b/config/locales/ru.yml index cd97306c8b7..1935bb8e695 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -1559,3 +1559,4 @@ ru: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 50de2074bff..5c3e4c6a2ae 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -1478,3 +1478,4 @@ sk: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 175c1971fe8..3eb5d94d9f6 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -1489,3 +1489,4 @@ sl: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 462ced05028..a833b67341d 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -1451,3 +1451,4 @@ sq: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/sr-YU.yml b/config/locales/sr-YU.yml index 20ec9134243..c9b85126c18 100644 --- a/config/locales/sr-YU.yml +++ b/config/locales/sr-YU.yml @@ -1491,3 +1491,4 @@ sr-YU: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 2fd54f87b10..1f5e1d24b6b 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -1490,3 +1490,4 @@ sr: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 767689f39ce..2f919b8980b 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -1522,3 +1522,4 @@ sv: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/ta-IN.yml b/config/locales/ta-IN.yml index d14a2ba72df..25e2b958d2e 100644 --- a/config/locales/ta-IN.yml +++ b/config/locales/ta-IN.yml @@ -1445,3 +1445,4 @@ ta-IN: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/th.yml b/config/locales/th.yml index d26f9f9ca82..39309a59315 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -1485,3 +1485,4 @@ th: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 5020ae231df..57477e4ad3b 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -1488,3 +1488,4 @@ tr: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 79bbf9df952..2e0b781c295 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -1477,3 +1477,4 @@ uk: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 871ab49d48f..366b8d79d89 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -1494,3 +1494,4 @@ vi: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index b80aec636da..f4853066900 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -1506,3 +1506,4 @@ label_option_auto_lang: 自動選取語言 label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity diff --git a/config/locales/zh.yml b/config/locales/zh.yml index bacc6159393..4739d33a648 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -1425,3 +1425,4 @@ zh: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + field_last_activity_date: Last activity From 6d89e6a9ed6c2b62e84cacf3fabc856bb71da154 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Sat, 11 May 2024 08:16:31 +0000 Subject: [PATCH 017/459] Traditional Chinese translation update (#40658). Patch by ChunChang (Nagaharu) Lo (@shortie). git-svn-id: https://svn.redmine.org/redmine/trunk@22818 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/zh-TW.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index f4853066900..2374e0c4e56 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -1504,6 +1504,6 @@ field_name_or_email_or_login: 姓名, 電子郵件或帳戶名稱 text_default_active_job_queue_changed: 已變更僅適用於開發/測試環境的佇列適配器 (queue adapter) label_option_auto_lang: 自動選取語言 - label_issue_attachment_added: Attachment added - field_estimated_remaining_hours: Estimated remaining time - field_last_activity_date: Last activity + label_issue_attachment_added: 附加檔案已新增 + field_estimated_remaining_hours: 預估剩餘工時 + field_last_activity_date: 最近一次活動 From 47099ccd3a6aa54c59541f87e98a88358021be2a Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Sat, 11 May 2024 08:35:27 +0000 Subject: [PATCH 018/459] Fixes issue list filter "Watched by: me" only shows issues watched via group for projects with the @view_issue_watchers@ permission (#40412). git-svn-id: https://svn.redmine.org/redmine/trunk@22819 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/issue_query.rb | 4 +++- test/unit/query_test.rb | 11 ++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb index 0895e80749c..687a8bdba90 100644 --- a/app/models/issue_query.rb +++ b/app/models/issue_query.rb @@ -551,7 +551,9 @@ def sql_for_spent_time_field(field, operator, value) def sql_for_watcher_id_field(field, operator, value) db_table = Watcher.table_name - me, others = value.partition {|id| ['0', User.current.id.to_s].include?(id)} + me_ids = [0, User.current.id] + me_ids = me_ids.concat(User.current.groups.pluck(:id)) + me, others = value.partition {|id| me_ids.include?(id.to_i)} sql = if others.any? "SELECT #{Issue.table_name}.id FROM #{Issue.table_name} " + diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index cf11bf10e4c..2aa10c5e99f 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -1376,7 +1376,7 @@ def test_filter_project_parent_id_with_my_bookmarks assert_equal Project.where(parent_id: bookmarks).ids.sort, result.map(&:id).sort end - def test_filter_watched_issues + def test_filter_watched_issues_by_user User.current = User.find(1) query = IssueQuery.new( @@ -1384,7 +1384,7 @@ def test_filter_watched_issues :filters => { 'watcher_id' => { :operator => '=', - :values => ['me'] + :values => [User.current.id] } } ) @@ -1394,13 +1394,17 @@ def test_filter_watched_issues assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id) end - def test_filter_watched_issues_with_groups_also + def test_filter_watched_issues_by_me_should_include_user_groups user = User.find(2) group = Group.find(10) group.users << user Issue.find(3).add_watcher(user) Issue.find(7).add_watcher(group) + manager = Role.find(1) + # view_issue_watchers permission is not required to see watched issues by current user or user groups + manager.remove_permission! :view_issue_watchers User.current = user + query = IssueQuery.new( :name => '_', @@ -1412,6 +1416,7 @@ def test_filter_watched_issues_with_groups_also } ) result = find_issues_with_query(query) + assert_not_nil result assert !result.empty? assert_equal [3, 7], result.sort_by(&:id).pluck(:id) From bd6a07cd1414cf3a253fe0bd2837d35bc6f3e86f Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Sat, 11 May 2024 08:53:42 +0000 Subject: [PATCH 019/459] Adds test to check @view_issue_watchers@ permission when filter "Watched by" (#40412). git-svn-id: https://svn.redmine.org/redmine/trunk@22820 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/unit/query_test.rb | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index 2aa10c5e99f..efc59d6904f 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -1422,6 +1422,36 @@ def test_filter_watched_issues_by_me_should_include_user_groups assert_equal [3, 7], result.sort_by(&:id).pluck(:id) end + def test_filter_watched_issues_by_group_should_include_only_projects_with_permission + user = User.find(2) + group = Group.find(10) + + Issue.find(4).add_watcher(group) + Issue.find(2).add_watcher(group) + + developer = Role.find(2) + developer.remove_permission! :view_issue_watchers + + User.current = user + + query = + IssueQuery.new( + :name => '_', + :filters => { + 'watcher_id' => { + :operator => '=', + :values => [group.id] + } + } + ) + result = find_issues_with_query(query) + + assert_not_nil result + + # "Developer" role doesn't have the view_issue_watchers permission of issue's #4 project (OnlineStore). + assert_equal [2], result.pluck(:id) + end + def test_filter_unwatched_issues User.current = User.find(1) query = From 82b59cac2d5d4fb2dfeaf1dd990991ed7270d9d1 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Sun, 12 May 2024 05:58:17 +0000 Subject: [PATCH 020/459] Czech translation update for 5.1-stable (#40682, #40654). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Pavel Rosický (@ahorek). git-svn-id: https://svn.redmine.org/redmine/trunk@22821 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/cs.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/config/locales/cs.yml b/config/locales/cs.yml index e172edf0595..bc63b4380c0 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1445,14 +1445,14 @@ cs: text_subprojects_bulk_destroy: 'včetně jeho prodprojektu/ů: %{value}' field_current_password: Aktuální heslo sudo_mode_new_info_html: "Co se děje? Musíte znovu potvrdit vaše heslo, než učiníte jakoukoli - administrativní akci. To zaručí, že váš účet zůstane chráněný." + administrativní akci. To zaručí, že Váš účet zůstane chráněný." label_edited: Upraveno label_time_by_author: "%{time} %{author}" field_default_time_entry_activity: Výchozí aktivita stráveného času field_is_member_of_group: Člen skupiny - text_users_bulk_destroy_head: Chystáte se zmazat následující uživatele a všechna jejich data. Tato operace je + text_users_bulk_destroy_head: Chystáte se smazat následující uživatele a všechna jejich data. Tato operace je nevratná. Zamčení uživatelů bývá lepším řešením. - text_users_bulk_destroy_confirm: Pro potvrzení zadej "%{yes}" níže. + text_users_bulk_destroy_confirm: Pro potvrzení zadejte "%{yes}" níže. permission_select_project_publicity: Nastav projekt jako veřejný nebo soukromý label_auto_watch_on_issue_created: Úkoly, které jsem vytvořil field_any_searchable: Jakýkoli vyhledávatelný text @@ -1464,10 +1464,10 @@ cs: label_changed_from: změněno od label_issue_statuses_description: Popis stavů úkolů label_open_issue_statuses_description: Zobraz popis všech stavů úkolů - text_select_apply_issue_status: Vyber stav úkolu - field_name_or_email_or_login: Name, email or login - text_default_active_job_queue_changed: Default queue adapter which is well suited - only for dev/test changed + text_select_apply_issue_status: Vyberte stav úkolu + field_name_or_email_or_login: Jméno, email nebo přihlášení + text_default_active_job_queue_changed: Výchozí adaptér fronty, vhodný pouze pro + vývoj/testování, byl změněn label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time From 8069401f794b169e43078a17d107c007360bb72a Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Sun, 12 May 2024 06:17:23 +0000 Subject: [PATCH 021/459] Czech translation update (#40654). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Pavel Rosický (@ahorek). git-svn-id: https://svn.redmine.org/redmine/trunk@22823 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/cs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/cs.yml b/config/locales/cs.yml index bc63b4380c0..8f14bb3b276 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1469,6 +1469,6 @@ cs: text_default_active_job_queue_changed: Výchozí adaptér fronty, vhodný pouze pro vývoj/testování, byl změněn label_option_auto_lang: auto - label_issue_attachment_added: Attachment added - field_estimated_remaining_hours: Estimated remaining time + label_issue_attachment_added: Příloha přidána + field_estimated_remaining_hours: Odhadovaný zbývající čas field_last_activity_date: Last activity From fb9bc74dd4781adf0a79e1b05c1ccb034b3e424b Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Mon, 13 May 2024 07:45:20 +0000 Subject: [PATCH 022/459] Fix RuboCop offense Style/RedundantSelfAssignment (#40412). git-svn-id: https://svn.redmine.org/redmine/trunk@22826 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/issue_query.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb index 687a8bdba90..c4b08158fd9 100644 --- a/app/models/issue_query.rb +++ b/app/models/issue_query.rb @@ -552,7 +552,7 @@ def sql_for_spent_time_field(field, operator, value) def sql_for_watcher_id_field(field, operator, value) db_table = Watcher.table_name me_ids = [0, User.current.id] - me_ids = me_ids.concat(User.current.groups.pluck(:id)) + me_ids.concat(User.current.groups.pluck(:id)) me, others = value.partition {|id| me_ids.include?(id.to_i)} sql = if others.any? From 2531e194f157e687a79b9db9fd8cf104eb66a103 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Mon, 13 May 2024 08:12:09 +0000 Subject: [PATCH 023/459] Fix RuboCop offense Style/RedundantSelfAssignment (#39887). git-svn-id: https://svn.redmine.org/redmine/trunk@22827 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .rubocop_todo.yml | 5 ----- lib/redmine/menu_manager.rb | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 609cdd834ab..3523536c631 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1421,11 +1421,6 @@ Style/RedundantReturn: Style/RedundantSelf: Enabled: false -# This cop supports unsafe autocorrection (--autocorrect-all). -Style/RedundantSelfAssignment: - Exclude: - - 'lib/redmine/menu_manager.rb' - # This cop supports safe autocorrection (--autocorrect). Style/RedundantSelfAssignmentBranch: Exclude: diff --git a/lib/redmine/menu_manager.rb b/lib/redmine/menu_manager.rb index 19169cfb759..5846011e246 100644 --- a/lib/redmine/menu_manager.rb +++ b/lib/redmine/menu_manager.rb @@ -381,7 +381,7 @@ def prepend(child) # Adds a child at given position def add_at(child, position) - @children = @children.insert(position, child) + @children.insert(position, child) child.parent = self child end From 434155af5aa40a50166278d8c24acef9ba102e15 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Mon, 13 May 2024 08:34:53 +0000 Subject: [PATCH 024/459] Update roadie-rails to 3.2.0 (#40685). git-svn-id: https://svn.redmine.org/redmine/trunk@22828 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 0c95a2456e6..c42714d5775 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,7 @@ gem 'rails', '7.1.2' gem 'rouge', '~> 4.2.0' gem 'mini_mime', '~> 1.1.0' gem "actionpack-xml_parser" -gem 'roadie-rails', '~> 3.1.0' +gem 'roadie-rails', '~> 3.2.0' gem 'marcel' gem 'mail', '~> 2.8.1' gem 'nokogiri', '~> 1.16.0' From 3761510af8b373931bc2c92567ea1d00e99415a7 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Tue, 14 May 2024 07:44:05 +0000 Subject: [PATCH 025/459] Fix slow display of projects list when including project description column (#40610). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22829 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/projects_queries_helper.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/helpers/projects_queries_helper.rb b/app/helpers/projects_queries_helper.rb index 3319576513c..dc540a432b3 100644 --- a/app/helpers/projects_queries_helper.rb +++ b/app/helpers/projects_queries_helper.rb @@ -27,7 +27,13 @@ def column_value(column, item, value) (tag.span(class: 'icon icon-user my-project', title: l(:label_my_projects)) if User.current.member_of?(item)) + (tag.span(class: 'icon icon-bookmarked-project', title: l(:label_my_bookmarks)) if User.current.bookmarked_project_ids.include?(item.id)) when :short_description - item.description? ? content_tag('div', textilizable(item, :short_description), :class => "wiki") : '' + if item.description? + # Sets :inline_attachments to false to avoid performance issues + # caused by unnecessary loading of attachments + content_tag('div', textilizable(item, :short_description, :inline_attachments => false), :class => 'wiki') + else + '' + end when :homepage item.homepage? ? content_tag('div', textilizable(item, :homepage), :class => "wiki") : '' when :status From 250414c3539ecd31bbad0b6ae4f4cf94b2b1864e Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Tue, 14 May 2024 08:04:04 +0000 Subject: [PATCH 026/459] Explicitly reference table name in Project#like scope to avoid ambiguity (#40691). Patch by Vincent Robert (@Nanego). git-svn-id: https://svn.redmine.org/redmine/trunk@22830 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index abac2a1f0d2..2b3280651d2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -110,7 +110,7 @@ class Project < ApplicationRecord scope :like, (lambda do |arg| if arg.present? pattern = "%#{sanitize_sql_like arg.to_s.strip}%" - where("LOWER(identifier) LIKE LOWER(:p) ESCAPE :s OR LOWER(name) LIKE LOWER(:p) ESCAPE :s", :p => pattern, :s => '\\') + where("LOWER(#{Project.table_name}.identifier) LIKE LOWER(:p) ESCAPE :s OR LOWER(#{Project.table_name}.name) LIKE LOWER(:p) ESCAPE :s", :p => pattern, :s => '\\') end end) scope :sorted, lambda {order(:lft)} From 9189837e7bd1066f267ebad54620bb21ef17af63 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Thu, 16 May 2024 07:20:19 +0000 Subject: [PATCH 027/459] Ignore statuses in Project#rolled_up_statuses which only have an identity transition defined (#40693). Patch by Holger Just (@hjust). git-svn-id: https://svn.redmine.org/redmine/trunk@22833 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/project.rb | 1 + test/functional/reports_controller_test.rb | 2 ++ test/unit/project_test.rb | 2 ++ 3 files changed, 5 insertions(+) diff --git a/app/models/project.rb b/app/models/project.rb index 2b3280651d2..909080a112d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -494,6 +494,7 @@ def rolled_up_trackers_base_scope def rolled_up_statuses issue_status_ids = WorkflowTransition. where(:tracker_id => rolled_up_trackers.map(&:id)). + where('old_status_id <> new_status_id'). distinct. pluck(:old_status_id, :new_status_id). flatten. diff --git a/test/functional/reports_controller_test.rb b/test/functional/reports_controller_test.rb index 67ea188f2e7..9f6624f6a8c 100644 --- a/test/functional/reports_controller_test.rb +++ b/test/functional/reports_controller_test.rb @@ -107,6 +107,8 @@ def test_get_issue_report_details_by_tracker_should_show_only_statuses_used_by_t WorkflowTransition.create(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4) WorkflowTransition.create(:role_id => 1, :tracker_id => 1, :old_status_id => 2, :new_status_id => 5) WorkflowTransition.create(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :new_status_id => 6) + WorkflowTransition.create(:role_id => 1, :tracker_id => 2, :old_status_id => 3, :new_status_id => 3) + with_settings :display_subprojects_issues => '0' do get(:issue_report_details, :params => {:id => 1, :detail => 'tracker'}) end diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb index a7047d71c0f..dc7d00fe855 100644 --- a/test/unit/project_test.rb +++ b/test/unit/project_test.rb @@ -534,6 +534,8 @@ def test_rolled_up_statuses WorkflowTransition.create(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4) WorkflowTransition.create(:role_id => 1, :tracker_id => 1, :old_status_id => 2, :new_status_id => 3) WorkflowTransition.create(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :new_status_id => 3) + WorkflowTransition.create(:role_id => 1, :tracker_id => 1, :old_status_id => 5, :new_status_id => 5) + WorkflowTransition.create(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 5) assert_kind_of IssueStatus, project.rolled_up_statuses.first assert_equal IssueStatus.find(1), project.rolled_up_statuses.first From f4c7e08d0f4601bdbfade1c5c216a759daeb29d9 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Thu, 16 May 2024 08:38:04 +0000 Subject: [PATCH 028/459] Key/value-pair custom field type not available to all customizable contents (#27543). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Felix Schäfer (@felix) and Takenori TAKAKI (@takenory). git-svn-id: https://svn.redmine.org/redmine/trunk@22834 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/field_format.rb | 2 ++ .../lib/redmine/field_format/enumeration_format_test.rb | 4 ++++ test/unit/lib/redmine/field_format/field_format_test.rb | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/lib/redmine/field_format.rb b/lib/redmine/field_format.rb index 9ee57cca81b..148cccadc88 100644 --- a/lib/redmine/field_format.rb +++ b/lib/redmine/field_format.rb @@ -829,6 +829,8 @@ def value_join_alias(custom_field) end class EnumerationFormat < RecordList + self.customized_class_names = nil + add 'enumeration' self.form_partial = 'custom_fields/formats/enumeration' diff --git a/test/unit/lib/redmine/field_format/enumeration_format_test.rb b/test/unit/lib/redmine/field_format/enumeration_format_test.rb index 74a637fc412..fdae2ff6f26 100644 --- a/test/unit/lib/redmine/field_format/enumeration_format_test.rb +++ b/test/unit/lib/redmine/field_format/enumeration_format_test.rb @@ -98,4 +98,8 @@ def test_value_from_keyword_for_multiple_custom_field_should_return_enumeration_ assert_equal [@foo.id], @field.value_from_keyword('foo, baz', nil) assert_equal [], @field.value_from_keyword('baz', nil) end + + def test_customized_class_names_should_overrided_to_nil + assert_nil Redmine::FieldFormat::EnumerationFormat.customized_class_names + end end diff --git a/test/unit/lib/redmine/field_format/field_format_test.rb b/test/unit/lib/redmine/field_format/field_format_test.rb index f71d83e3401..6418917f29f 100644 --- a/test/unit/lib/redmine/field_format/field_format_test.rb +++ b/test/unit/lib/redmine/field_format/field_format_test.rb @@ -111,4 +111,10 @@ def test_text_field_with_url_pattern_should_encode_values assert_equal "foo bar", field.format.formatted_custom_value(self, custom_value, false) assert_equal 'foo bar', field.format.formatted_custom_value(self, custom_value, true) end + + def test_as_select_should_return_enumeration_for_all_classes + %w(Issue TimeEntry Project Version Document User Group TimeEntryActivity IssuePriority DocumentCategory).each do |klass| + assert_include ['Key/value list', 'enumeration'], Redmine::FieldFormat.as_select(klass) + end + end end From 58e9cd420adad1802d42828c8efedca0e6fed2d1 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Thu, 16 May 2024 11:31:27 +0000 Subject: [PATCH 029/459] Japanese translation update (#40703). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22835 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/ja.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 3756b62bea0..7511951d975 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1439,6 +1439,6 @@ ja: field_name_or_email_or_login: 姓名・メールアドレス・ログインID text_default_active_job_queue_changed: キューアダプターがデフォルト (開発・テスト用) 以外のものに変更済み label_option_auto_lang: 自動設定 - label_issue_attachment_added: Attachment added - field_estimated_remaining_hours: Estimated remaining time - field_last_activity_date: Last activity + label_issue_attachment_added: 添付ファイルの追加 + field_estimated_remaining_hours: 残工数 + field_last_activity_date: 最終活動日 From a9518e28b86a330cbbc2cd2c9170e1cd38c458e2 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Sat, 18 May 2024 05:56:55 +0000 Subject: [PATCH 030/459] Fix RuboCop offense Rails/HttpStatus (#39889). git-svn-id: https://svn.redmine.org/redmine/trunk@22837 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .rubocop_todo.yml | 22 ----- app/controllers/attachments_controller.rb | 4 +- app/controllers/boards_controller.rb | 4 +- app/controllers/custom_fields_controller.rb | 4 +- app/controllers/enumerations_controller.rb | 4 +- app/controllers/issue_relations_controller.rb | 4 +- app/controllers/issue_statuses_controller.rb | 4 +- app/controllers/issues_controller.rb | 2 +- app/controllers/mail_handler_controller.rb | 2 +- app/controllers/members_controller.rb | 4 +- app/controllers/my_controller.rb | 2 +- app/controllers/repositories_controller.rb | 2 +- app/controllers/roles_controller.rb | 4 +- app/controllers/sys_controller.rb | 12 +-- app/controllers/timelog_controller.rb | 2 +- app/controllers/trackers_controller.rb | 4 +- app/controllers/watchers_controller.rb | 8 +- test/functional/account_controller_test.rb | 8 +- test/functional/activities_controller_test.rb | 6 +- .../functional/attachments_controller_test.rb | 44 ++++----- .../functional/attachments_visibility_test.rb | 2 +- .../auth_sources_controller_test.rb | 4 +- test/functional/boards_controller_test.rb | 4 +- test/functional/comments_controller_test.rb | 2 +- .../context_menus_controller_test.rb | 4 +- ...stom_field_enumerations_controller_test.rb | 4 +- .../custom_fields_controller_test.rb | 6 +- .../email_addresses_controller_test.rb | 16 +-- .../enumerations_controller_test.rb | 10 +- test/functional/groups_controller_test.rb | 4 +- test/functional/imports_controller_test.rb | 12 +-- .../issue_categories_controller_test.rb | 2 +- .../issue_relations_controller_test.rb | 4 +- .../issue_statuses_controller_test.rb | 2 +- test/functional/issues_controller_test.rb | 98 +++++++++---------- .../issues_controller_transaction_test.rb | 8 +- .../issues_custom_fields_visibility_test.rb | 6 +- test/functional/journals_controller_test.rb | 10 +- .../mail_handler_controller_test.rb | 12 +-- test/functional/members_controller_test.rb | 2 +- test/functional/messages_controller_test.rb | 8 +- test/functional/my_controller_test.rb | 2 +- test/functional/news_controller_test.rb | 8 +- test/functional/projects_controller_test.rb | 26 ++--- test/functional/queries_controller_test.rb | 24 ++--- test/functional/reports_controller_test.rb | 2 +- .../repositories_bazaar_controller_test.rb | 4 +- .../repositories_controller_test.rb | 10 +- .../repositories_cvs_controller_test.rb | 4 +- ...repositories_filesystem_controller_test.rb | 4 +- .../repositories_git_controller_test.rb | 10 +- .../repositories_mercurial_controller_test.rb | 8 +- ...repositories_subversion_controller_test.rb | 10 +- test/functional/roles_controller_test.rb | 4 +- test/functional/search_controller_test.rb | 8 +- test/functional/settings_controller_test.rb | 6 +- test/functional/sys_controller_test.rb | 6 +- test/functional/timelog_controller_test.rb | 26 ++--- test/functional/trackers_controller_test.rb | 2 +- test/functional/users_controller_test.rb | 26 ++--- test/functional/watchers_controller_test.rb | 12 +-- test/functional/welcome_controller_test.rb | 4 +- test/functional/wiki_controller_test.rb | 28 +++--- test/functional/wikis_controller_test.rb | 2 +- test/functional/workflows_controller_test.rb | 18 ++-- test/integration/account_test.rb | 2 +- test/integration/api_test/api_test.rb | 2 +- test/integration/api_test/attachments_test.rb | 10 +- .../api_test/authentication_test.rb | 30 +++--- .../integration/api_test/enumerations_test.rb | 2 +- test/integration/api_test/groups_test.rb | 4 +- test/integration/api_test/issues_test.rb | 6 +- .../integration/api_test/time_entries_test.rb | 4 +- test/integration/api_test/users_test.rb | 2 +- test/integration/api_test/wiki_pages_test.rb | 22 ++--- test/integration/application_test.rb | 16 +-- test/integration/attachments_test.rb | 8 +- test/integration/issues_test.rb | 14 +-- .../field_format/attachment_format_test.rb | 8 +- test/integration/projects_test.rb | 6 +- test/integration/sessions_test.rb | 12 +-- test/integration/sudo_mode_test.rb | 4 +- test/integration/users_test.rb | 2 +- 83 files changed, 376 insertions(+), 398 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 3523536c631..015c61dd878 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -588,28 +588,6 @@ Rails/HasManyOrHasOneDependent: - 'app/models/wiki.rb' - 'app/models/wiki_page.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: numeric, symbolic -Rails/HttpStatus: - Exclude: - - 'app/controllers/attachments_controller.rb' - - 'app/controllers/boards_controller.rb' - - 'app/controllers/custom_fields_controller.rb' - - 'app/controllers/enumerations_controller.rb' - - 'app/controllers/issue_relations_controller.rb' - - 'app/controllers/issue_statuses_controller.rb' - - 'app/controllers/issues_controller.rb' - - 'app/controllers/mail_handler_controller.rb' - - 'app/controllers/members_controller.rb' - - 'app/controllers/my_controller.rb' - - 'app/controllers/repositories_controller.rb' - - 'app/controllers/roles_controller.rb' - - 'app/controllers/sys_controller.rb' - - 'app/controllers/timelog_controller.rb' - - 'app/controllers/trackers_controller.rb' - - 'app/controllers/watchers_controller.rb' - # Configuration parameters: Include. # Include: spec/**/*.rb, test/**/*.rb Rails/I18nLocaleAssignment: diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index db95d5df422..90c3c707094 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -93,7 +93,7 @@ def thumbnail end else # No thumbnail for the attachment or thumbnail could not be created - head 404 + head :not_found end end @@ -101,7 +101,7 @@ def upload # Make sure that API users get used to set this content type # as it won't trigger Rails' automatic parsing of the request body for parameters unless request.media_type == 'application/octet-stream' - head 406 + head :not_acceptable return end diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb index 5782a2f60a0..194f5b773dc 100644 --- a/app/controllers/boards_controller.rb +++ b/app/controllers/boards_controller.rb @@ -93,12 +93,12 @@ def update flash[:notice] = l(:notice_successful_update) redirect_to_settings_in_projects end - format.js {head 200} + format.js {head :ok} end else respond_to do |format| format.html {render :action => 'edit'} - format.js {head 422} + format.js {head :unprocessable_entity} end end end diff --git a/app/controllers/custom_fields_controller.rb b/app/controllers/custom_fields_controller.rb index fed45d3ea85..68eeb6e1241 100644 --- a/app/controllers/custom_fields_controller.rb +++ b/app/controllers/custom_fields_controller.rb @@ -70,12 +70,12 @@ def update flash[:notice] = l(:notice_successful_update) redirect_back_or_default edit_custom_field_path(@custom_field) end - format.js {head 200} + format.js {head :ok} end else respond_to do |format| format.html {render :action => 'edit'} - format.js {head 422} + format.js {head :unprocessable_entity} end end end diff --git a/app/controllers/enumerations_controller.rb b/app/controllers/enumerations_controller.rb index 664193fa782..b4851f1e2c9 100644 --- a/app/controllers/enumerations_controller.rb +++ b/app/controllers/enumerations_controller.rb @@ -65,12 +65,12 @@ def update flash[:notice] = l(:notice_successful_update) redirect_to enumerations_path end - format.js {head 200} + format.js {head :ok} end else respond_to do |format| format.html {render :action => 'edit'} - format.js {head 422} + format.js {head :unprocessable_entity} end end end diff --git a/app/controllers/issue_relations_controller.rb b/app/controllers/issue_relations_controller.rb index d487e095426..e64d9a1f764 100644 --- a/app/controllers/issue_relations_controller.rb +++ b/app/controllers/issue_relations_controller.rb @@ -29,7 +29,7 @@ def index @relations = @issue.relations respond_to do |format| - format.html {head 200} + format.html {head :ok} format.api end end @@ -38,7 +38,7 @@ def show raise Unauthorized unless @relation.visible? respond_to do |format| - format.html {head 200} + format.html {head :ok} format.api end end diff --git a/app/controllers/issue_statuses_controller.rb b/app/controllers/issue_statuses_controller.rb index 1048417a52b..0d6e2199e48 100644 --- a/app/controllers/issue_statuses_controller.rb +++ b/app/controllers/issue_statuses_controller.rb @@ -61,12 +61,12 @@ def update flash[:notice] = l(:notice_successful_update) redirect_to issue_statuses_path(:page => params[:page]) end - format.js {head 200} + format.js {head :ok} end else respond_to do |format| format.html {render :action => 'edit'} - format.js {head 422} + format.js {head :unprocessable_entity} end end end diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index b449d9ee913..76e7ed921cf 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -84,7 +84,7 @@ def index else respond_to do |format| format.html {render :layout => !request.xhr?} - format.any(:atom, :csv, :pdf) {head 422} + format.any(:atom, :csv, :pdf) {head :unprocessable_entity} format.api {render_validation_errors(@query)} end end diff --git a/app/controllers/mail_handler_controller.rb b/app/controllers/mail_handler_controller.rb index ca1468aac7c..bf871599e4a 100644 --- a/app/controllers/mail_handler_controller.rb +++ b/app/controllers/mail_handler_controller.rb @@ -70,7 +70,7 @@ def index def check_credential User.current = nil unless Setting.mail_handler_api_enabled? && secure_compare(params[:key].to_s, Setting.mail_handler_api_key.to_s) - render :plain => 'Access denied. Incoming emails WS is disabled or key is invalid.', :status => 403 + render :plain => 'Access denied. Incoming emails WS is disabled or key is invalid.', :status => :forbidden end end end diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index 239a48978c9..8d4f64bab43 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -36,14 +36,14 @@ def index @members = scope.includes(:principal, :roles).order(:id).limit(@limit).offset(@offset).to_a respond_to do |format| - format.html {head 406} + format.html {head :not_acceptable} format.api end end def show respond_to do |format| - format.html {head 406} + format.html {head :not_acceptable} format.api end end diff --git a/app/controllers/my_controller.rb b/app/controllers/my_controller.rb index e30ae093cb8..01fe3995cc7 100644 --- a/app/controllers/my_controller.rb +++ b/app/controllers/my_controller.rb @@ -195,6 +195,6 @@ def order_blocks @user = User.current @user.pref.order_blocks params[:group], params[:blocks] @user.pref.save - head 200 + head :ok end end diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 8deb3540468..08fa8c2d13e 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -89,7 +89,7 @@ def show @entries = @repository.entries(@path, @rev) @changeset = @repository.find_changeset_by_name(@rev) if request.xhr? - @entries ? render(:partial => 'dir_list_content') : head(200) + @entries ? render(:partial => 'dir_list_content') : head(:ok) else (show_error_not_found; return) unless @entries @changesets = @repository.latest_changesets(@path, @rev) diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index 3b4fe1b3038..f81144a5cf7 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -85,12 +85,12 @@ def update flash[:notice] = l(:notice_successful_update) redirect_to roles_path(:page => params[:page]) end - format.js {head 200} + format.js {head :ok} end else respond_to do |format| format.html {render :action => 'edit'} - format.js {head 422} + format.js {head :unprocessable_entity} end end end diff --git a/app/controllers/sys_controller.rb b/app/controllers/sys_controller.rb index f5e3335549b..7e785f951c9 100644 --- a/app/controllers/sys_controller.rb +++ b/app/controllers/sys_controller.rb @@ -37,16 +37,16 @@ def projects def create_project_repository project = Project.find(params[:id]) if project.repository - head 409 + head :conflict else logger.info "Repository for #{project.name} was reported to be created by #{request.remote_ip}." repository = Repository.factory(params[:vendor]) repository.safe_attributes = params[:repository] repository.project = project if repository.save - render :json => {repository.class.name.underscore.tr('/', '-') => {:id => repository.id, :url => repository.url}}, :status => 201 + render :json => {repository.class.name.underscore.tr('/', '-') => {:id => repository.id, :url => repository.url}}, :status => :created else - head 422 + head :unprocessable_entity end end end @@ -72,9 +72,9 @@ def fetch_changesets repository.fetch_changesets end end - head 200 + head :ok rescue ActiveRecord::RecordNotFound - head 404 + head :not_found end protected @@ -82,7 +82,7 @@ def fetch_changesets def check_enabled User.current = nil unless Setting.sys_api_enabled? && secure_compare(params[:key].to_s, Setting.sys_api_key.to_s) - render :plain => 'Access denied. Repository management WS is disabled or key is invalid.', :status => 403 + render :plain => 'Access denied. Repository management WS is disabled or key is invalid.', :status => :forbidden return false end end diff --git a/app/controllers/timelog_controller.rb b/app/controllers/timelog_controller.rb index a7ad7d8a676..13c8ff26a8f 100644 --- a/app/controllers/timelog_controller.rb +++ b/app/controllers/timelog_controller.rb @@ -90,7 +90,7 @@ def report def show respond_to do |format| # TODO: Implement html response - format.html {head 406} + format.html {head :not_acceptable} format.api end end diff --git a/app/controllers/trackers_controller.rb b/app/controllers/trackers_controller.rb index c8624c3987c..95cdcbc8fc9 100644 --- a/app/controllers/trackers_controller.rb +++ b/app/controllers/trackers_controller.rb @@ -73,7 +73,7 @@ def update flash[:notice] = l(:notice_successful_update) redirect_to trackers_path(:page => params[:page]) end - format.js {head 200} + format.js {head :ok} end else respond_to do |format| @@ -81,7 +81,7 @@ def update edit render :action => 'edit' end - format.js {head 422} + format.js {head :unprocessable_entity} end end end diff --git a/app/controllers/watchers_controller.rb b/app/controllers/watchers_controller.rb index 0f566e7f5f6..4113464bc2a 100644 --- a/app/controllers/watchers_controller.rb +++ b/app/controllers/watchers_controller.rb @@ -57,7 +57,7 @@ def create respond_to do |format| format.html do redirect_to_referer_or do - render(:html => 'Watcher added.', :status => 200, :layout => true) + render(:html => 'Watcher added.', :status => :ok, :layout => true) end end format.js {@users = users_for_new_watcher} @@ -71,7 +71,7 @@ def append @users = Principal.assignable_watchers.where(:id => user_ids).to_a end if @users.blank? - head 200 + head :ok end end @@ -83,7 +83,7 @@ def destroy respond_to do |format| format.html do redirect_to_referer_or do - render(:html => 'Watcher removed.', :status => 200, :layout => true) + render(:html => 'Watcher removed.', :status => :ok, :layout => true) end end format.js @@ -132,7 +132,7 @@ def set_watcher(watchables, user, watching) format.html do text = watching ? 'Watcher added.' : 'Watcher removed.' redirect_to_referer_or do - render(:html => text, :status => 200, :layout => true) + render(:html => text, :status => :ok, :layout => true) end end format.js do diff --git a/test/functional/account_controller_test.rb b/test/functional/account_controller_test.rb index 1bf1bb1bbf1..083b2bafd19 100644 --- a/test/functional/account_controller_test.rb +++ b/test/functional/account_controller_test.rb @@ -230,7 +230,7 @@ def test_login_should_rescue_auth_source_exception :password => 'jsmith' } ) - assert_response 500 + assert_response :internal_server_error assert_select_error /Something wrong/ end @@ -243,7 +243,7 @@ def test_login_should_reset_session :password => 'jsmith' } ) - assert_response 302 + assert_response :found end def test_login_should_strip_whitespaces_from_user_name @@ -254,7 +254,7 @@ def test_login_should_strip_whitespaces_from_user_name :password => 'jsmith' } ) - assert_response 302 + assert_response :found assert_equal 2, @request.session[:user_id] end @@ -283,7 +283,7 @@ def test_logout_should_reset_session @request.session[:user_id] = 2 post :logout - assert_response 302 + assert_response :found end def test_get_register_with_registration_on diff --git a/test/functional/activities_controller_test.rb b/test/functional/activities_controller_test.rb index 20f0b123dfb..3fb0c1fbc48 100644 --- a/test/functional/activities_controller_test.rb +++ b/test/functional/activities_controller_test.rb @@ -74,7 +74,7 @@ def test_index_subproject_checkbox_should_check_descendants_visibility def test_project_index_with_invalid_project_id_should_respond_404 get(:index, :params => {:id => 299}) - assert_response 404 + assert_response :not_found end def test_previous_project_index @@ -131,7 +131,7 @@ def test_user_index_with_invalid_user_id_should_respond_404 :user_id => 299 } ) - assert_response 404 + assert_response :not_found end def test_user_index_with_non_visible_user_id_should_respond_404 @@ -143,7 +143,7 @@ def test_user_index_with_non_visible_user_id_should_respond_404 :user_id => user.id } - assert_response 404 + assert_response :not_found end def test_index_atom_feed diff --git a/test/functional/attachments_controller_test.rb b/test/functional/attachments_controller_test.rb index 7fd72ae52a9..2af340f6d49 100644 --- a/test/functional/attachments_controller_test.rb +++ b/test/functional/attachments_controller_test.rb @@ -267,7 +267,7 @@ def test_show_file_without_container_should_be_allowed_to_author attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2) @request.session[:user_id] = 2 get(:show, :params => {:id => attachment.id}) - assert_response 200 + assert_response :ok end def test_show_file_without_container_should_be_denied_to_other_users @@ -276,7 +276,7 @@ def test_show_file_without_container_should_be_denied_to_other_users @request.session[:user_id] = 3 get(:show, :params => {:id => attachment.id}) - assert_response 403 + assert_response :forbidden end def test_show_issue_attachment_should_highlight_issues_menu_item @@ -287,7 +287,7 @@ def test_show_issue_attachment_should_highlight_issues_menu_item def test_show_invalid_should_respond_with_404 get(:show, :params => {:id => 999}) - assert_response 404 + assert_response :not_found end def test_show_renders_pagination @@ -307,7 +307,7 @@ def test_download_text_file @request.env["HTTP_IF_NONE_MATCH"] = etag get(:download, :params => {:id => 4}) - assert_response 304 + assert_response :not_modified end def test_download_js_file @@ -352,7 +352,7 @@ def test_download_should_assign_application_octet_stream_if_content_type_is_not_ def test_download_missing_file get(:download, :params => {:id => 2}) - assert_response 404 + assert_response :not_found end def test_download_should_be_denied_without_permission @@ -383,7 +383,7 @@ def test_thumbnail :id => 16 } ) - assert_response 304 + assert_response :not_modified end def test_thumbnail_should_not_exceed_maximum_size @@ -418,7 +418,7 @@ def test_thumbnail_should_return_404_for_non_image_attachment :id => 15 } ) - assert_response 404 + assert_response :not_found end def test_thumbnail_should_return_404_if_thumbnail_generation_failed @@ -430,7 +430,7 @@ def test_thumbnail_should_return_404_if_thumbnail_generation_failed :id => 16 } ) - assert_response 404 + assert_response :not_found end def test_thumbnail_should_be_denied_without_permission @@ -499,7 +499,7 @@ def test_edit_all_with_invalid_object_should_return_404 :object_id => '999' } ) - assert_response 404 + assert_response :not_found end def test_edit_all_for_object_that_is_not_visible_should_return_403 @@ -510,7 +510,7 @@ def test_edit_all_for_object_that_is_not_visible_should_return_403 :object_id => '4' } ) - assert_response 403 + assert_response :forbidden end def test_edit_all_issue_attachment_by_user_without_edit_issue_permission_on_tracker_should_return_404 @@ -527,7 +527,7 @@ def test_edit_all_issue_attachment_by_user_without_edit_issue_permission_on_trac :object_id => '4' } ) - assert_response 404 + assert_response :not_found end def test_update_all @@ -549,7 +549,7 @@ def test_update_all } } ) - assert_response 302 + assert_response :found attachment = Attachment.find(4) assert_equal 'newname.rb', attachment.filename assert_equal 'Renamed', attachment.description @@ -592,7 +592,7 @@ def test_download_all_with_valid_container :object_id => '2' } ) - assert_response 200 + assert_response :ok assert_equal response.headers['Content-Type'], 'application/zip' assert_match /issue-2-attachments.zip/, response.headers['Content-Disposition'] assert_not_includes Dir.entries(Rails.root.join('tmp')), /attachments_zip/ @@ -607,7 +607,7 @@ def test_download_all_with_invalid_container :object_id => '999' } ) - assert_response 404 + assert_response :not_found end def test_download_all_without_readable_attachments @@ -620,7 +620,7 @@ def test_download_all_without_readable_attachments } ) assert_equal Issue.find(1).attachments, [] - assert_response 404 + assert_response :not_found end def test_download_all_with_invisible_journal @@ -636,7 +636,7 @@ def test_download_all_with_invisible_journal :object_id => '3' } ) - assert_response 403 + assert_response :forbidden end def test_download_all_with_maximum_bulk_download_size_larger_than_attachments @@ -705,7 +705,7 @@ def test_destroy_wiki_page_attachment :id => 3 } ) - assert_response 302 + assert_response :found end end @@ -719,7 +719,7 @@ def test_destroy_project_attachment :id => 8 } ) - assert_response 302 + assert_response :found end end @@ -733,7 +733,7 @@ def test_destroy_version_attachment :id => 9 } ) - assert_response 302 + assert_response :found end end @@ -748,7 +748,7 @@ def test_destroy_version_attachment_with_issue_tracking_disabled :id => 9 } ) - assert_response 302 + assert_response :found end end @@ -762,7 +762,7 @@ def test_destroy_without_permission } ) end - assert_response 302 + assert_response :found assert Attachment.find_by_id(3) end @@ -783,7 +783,7 @@ def test_destroy_issue_attachment_by_user_without_edit_issue_permission_on_track ) end - assert_response 403 + assert_response :forbidden assert Attachment.find_by_id(7) end end diff --git a/test/functional/attachments_visibility_test.rb b/test/functional/attachments_visibility_test.rb index e9692dfcbd5..ad1d83f934e 100644 --- a/test/functional/attachments_visibility_test.rb +++ b/test/functional/attachments_visibility_test.rb @@ -55,6 +55,6 @@ def test_attachment_should_be_visible_with_permission @field.update!(:visible => false, :role_ids => [1]) get :show, :params => {:id => @attachment.id} - assert_response 403 + assert_response :forbidden end end diff --git a/test/functional/auth_sources_controller_test.rb b/test/functional/auth_sources_controller_test.rb index 7fdd2f3769f..e470e8e1b49 100644 --- a/test/functional/auth_sources_controller_test.rb +++ b/test/functional/auth_sources_controller_test.rb @@ -48,7 +48,7 @@ def test_new_with_invalid_type_should_respond_with_404 :type => 'foo' } ) - assert_response 404 + assert_response :not_found end def test_create @@ -129,7 +129,7 @@ def test_edit_invalid_should_respond_with_404 :id => 99 } ) - assert_response 404 + assert_response :not_found end def test_update diff --git a/test/functional/boards_controller_test.rb b/test/functional/boards_controller_test.rb index e6fbf5c8dff..4062c3fb878 100644 --- a/test/functional/boards_controller_test.rb +++ b/test/functional/boards_controller_test.rb @@ -44,7 +44,7 @@ def test_index_not_found :project_id => 97 } ) - assert_response 404 + assert_response :not_found end def test_index_should_show_messages_if_only_one_board @@ -159,7 +159,7 @@ def test_show_not_found :id => 97 } ) - assert_response 404 + assert_response :not_found end def test_new diff --git a/test/functional/comments_controller_test.rb b/test/functional/comments_controller_test.rb index bd25a2673cc..e1118f77e70 100644 --- a/test/functional/comments_controller_test.rb +++ b/test/functional/comments_controller_test.rb @@ -75,7 +75,7 @@ def test_create_should_be_denied_if_news_is_not_commentable } } ) - assert_response 403 + assert_response :forbidden end end diff --git a/test/functional/context_menus_controller_test.rb b/test/functional/context_menus_controller_test.rb index ed3d40c4593..c8d4f798d1f 100644 --- a/test/functional/context_menus_controller_test.rb +++ b/test/functional/context_menus_controller_test.rb @@ -384,12 +384,12 @@ def test_context_menu_with_issue_that_is_not_visible_should_fail :ids => [1, 4] # issue 4 is not visible } ) - assert_response 302 + assert_response :found end def test_should_respond_with_404_without_ids get :issues - assert_response 404 + assert_response :not_found end def test_time_entries_context_menu diff --git a/test/functional/custom_field_enumerations_controller_test.rb b/test/functional/custom_field_enumerations_controller_test.rb index a431877868d..e7479049513 100644 --- a/test/functional/custom_field_enumerations_controller_test.rb +++ b/test/functional/custom_field_enumerations_controller_test.rb @@ -101,7 +101,7 @@ def test_update_each } } ) - assert_response 302 + assert_response :found @bar.reload assert_equal "Baz", @bar.name @@ -164,7 +164,7 @@ def test_destroy_enumeration_in_use_should_destroy_and_reassign_values :reassign_to_id => @bar.id } ) - assert_response 302 + assert_response :found end assert_equal @bar.id.to_s, group.reload.custom_field_value(@field) diff --git a/test/functional/custom_fields_controller_test.rb b/test/functional/custom_fields_controller_test.rb index 9ccb7acb8c8..b3fa614ba33 100644 --- a/test/functional/custom_fields_controller_test.rb +++ b/test/functional/custom_fields_controller_test.rb @@ -445,7 +445,7 @@ def test_create_with_project_ids } } ) - assert_response 302 + assert_response :found end field = IssueCustomField.order("id desc").first assert_equal [1, 3], field.projects.map(&:id).sort @@ -514,7 +514,7 @@ def test_create_with_enumerations :custom_field => {:name => 'Copy'} } ) - assert_response 302 + assert_response :found end field = IssueCustomField.order('id desc').first assert_equal 'Copy', field.name @@ -540,7 +540,7 @@ def test_edit_invalid_custom_field_should_render_404 :id => 99 } ) - assert_response 404 + assert_response :not_found end def test_update diff --git a/test/functional/email_addresses_controller_test.rb b/test/functional/email_addresses_controller_test.rb index 2468676b627..4265479076b 100644 --- a/test/functional/email_addresses_controller_test.rb +++ b/test/functional/email_addresses_controller_test.rb @@ -59,7 +59,7 @@ def test_index_by_admin_should_be_allowed def test_index_by_another_user_should_be_denied @request.session[:user_id] = 3 get(:index, :params => {:user_id => 2}) - assert_response 403 + assert_response :forbidden end def test_create @@ -74,7 +74,7 @@ def test_create } } ) - assert_response 302 + assert_response :found assert_redirected_to '/users/2/email_addresses' end email = EmailAddress.order('id DESC').first @@ -95,7 +95,7 @@ def test_create_as_js }, :xhr => true ) - assert_response 200 + assert_response :ok end end @@ -188,7 +188,7 @@ def test_update :notify => '0' } ) - assert_response 302 + assert_response :found assert_equal false, email.reload.notify end @@ -206,7 +206,7 @@ def test_update_as_js }, :xhr => true ) - assert_response 200 + assert_response :ok assert_equal false, email.reload.notify end @@ -245,7 +245,7 @@ def test_destroy :id => email.id } ) - assert_response 302 + assert_response :found assert_redirected_to '/users/2/email_addresses' end end @@ -263,7 +263,7 @@ def test_destroy_as_js }, :xhr => true ) - assert_response 200 + assert_response :ok end end @@ -278,7 +278,7 @@ def test_should_not_destroy_default :id => User.find(2).email_address.id } ) - assert_response 404 + assert_response :not_found end end diff --git a/test/functional/enumerations_controller_test.rb b/test/functional/enumerations_controller_test.rb index 06b56d024af..a87d72d9f1f 100644 --- a/test/functional/enumerations_controller_test.rb +++ b/test/functional/enumerations_controller_test.rb @@ -35,7 +35,7 @@ def test_index def test_index_should_require_admin @request.session[:user_id] = nil get :index - assert_response 302 + assert_response :found end def test_new @@ -48,7 +48,7 @@ def test_new def test_new_with_invalid_type_should_respond_with_404 get(:new, :params => {:type => 'UnknownType'}) - assert_response 404 + assert_response :not_found end def test_create @@ -128,7 +128,7 @@ def test_edit def test_edit_invalid_should_respond_with_404 get(:edit, :params => {:id => 999}) - assert_response 404 + assert_response :not_found end def test_update @@ -177,7 +177,7 @@ def test_update_position } } ) - assert_response 302 + assert_response :found assert_equal 1, Enumeration.find(2).position end @@ -194,7 +194,7 @@ def test_update_custom_field_values } } ) - assert_response 302 + assert_response :found assert_equal "sample", enumeration.reload.custom_field_values.last.value end diff --git a/test/functional/groups_controller_test.rb b/test/functional/groups_controller_test.rb index 23b84de7e5b..ede4efce3c7 100644 --- a/test/functional/groups_controller_test.rb +++ b/test/functional/groups_controller_test.rb @@ -72,7 +72,7 @@ def test_show_should_display_custom_fields def test_show_invalid_should_return_404 get(:show, :params => {:id => 99}) - assert_response 404 + assert_response :not_found end def test_show_group_that_is_not_visible_should_return_404 @@ -80,7 +80,7 @@ def test_show_group_that_is_not_visible_should_return_404 @request.session[:user_id] = nil get :show, :params => {:id => 10} - assert_response 404 + assert_response :not_found end def test_show_should_display_only_visible_users diff --git a/test/functional/imports_controller_test.rb b/test/functional/imports_controller_test.rb index c368b64b9aa..42edf5ca524 100644 --- a/test/functional/imports_controller_test.rb +++ b/test/functional/imports_controller_test.rb @@ -61,7 +61,7 @@ def test_create_should_save_the_file :file => uploaded_test_file('import_issues.csv', 'text/csv') } ) - assert_response 302 + assert_response :found end assert_equal 2, import.user_id assert_match /\A[0-9a-f]+\z/, import.filename @@ -123,7 +123,7 @@ def test_post_settings_should_update_total_items_count } } ) - assert_response 302 + assert_response :found import.reload assert_equal 2, import.total_items end @@ -142,7 +142,7 @@ def test_post_settings_with_wrong_encoding_should_display_error } } ) - assert_response 200 + assert_response :ok import.reload assert_nil import.total_items assert_select 'div#flash_error', /not a valid UTF-8 encoded file/ @@ -162,7 +162,7 @@ def test_post_settings_with_invalid_encoding_should_display_error } } ) - assert_response 200 + assert_response :ok import.reload assert_nil import.total_items assert_select 'div#flash_error', /not a valid Shift_JIS encoded file/ @@ -182,7 +182,7 @@ def test_post_settings_with_mailformed_csv_should_display_error } } ) - assert_response 200 + assert_response :ok import.reload assert_nil import.total_items @@ -203,7 +203,7 @@ def test_post_settings_with_no_data_row_should_display_error } } ) - assert_response 200 + assert_response :ok import.reload assert_equal 0, import.total_items diff --git a/test/functional/issue_categories_controller_test.rb b/test/functional/issue_categories_controller_test.rb index 0e527fdc5e3..62b2d42e4bd 100644 --- a/test/functional/issue_categories_controller_test.rb +++ b/test/functional/issue_categories_controller_test.rb @@ -170,7 +170,7 @@ def test_update_not_found } } ) - assert_response 404 + assert_response :not_found end def test_destroy_category_not_in_use diff --git a/test/functional/issue_relations_controller_test.rb b/test/functional/issue_relations_controller_test.rb index 2497309bdd5..fadf1011b42 100644 --- a/test/functional/issue_relations_controller_test.rb +++ b/test/functional/issue_relations_controller_test.rb @@ -71,7 +71,7 @@ def test_create_on_invalid_issue } } ) - assert_response 404 + assert_response :not_found end end @@ -305,7 +305,7 @@ def test_destroy def test_destroy_invalid_relation assert_no_difference 'IssueRelation.count' do delete(:destroy, :params => {:id => '999'}) - assert_response 404 + assert_response :not_found end end diff --git a/test/functional/issue_statuses_controller_test.rb b/test/functional/issue_statuses_controller_test.rb index 099460624af..c7594f9a0c8 100644 --- a/test/functional/issue_statuses_controller_test.rb +++ b/test/functional/issue_statuses_controller_test.rb @@ -42,7 +42,7 @@ def test_index_by_anonymous_should_redirect_to_login_form def test_index_by_user_should_respond_with_406 @request.session[:user_id] = 2 get :index - assert_response 406 + assert_response :not_acceptable end def test_index_should_show_warning_when_no_workflow_is_defined diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index f7c87918836..53cfd814657 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -705,7 +705,7 @@ def test_index_with_invalid_query_id_should_respond_404 :query_id => 999 } ) - assert_response 404 + assert_response :not_found end def test_index_with_cross_project_query_in_session_should_show_project_issues @@ -734,7 +734,7 @@ def test_private_query_should_not_be_available_to_other_users ) @request.session[:user_id] = 3 get(:index, :params => {:query_id => q.id}) - assert_response 403 + assert_response :forbidden end def test_private_query_should_be_available_to_its_user @@ -2392,28 +2392,28 @@ def test_show_should_deny_non_member_access_without_permission Role.non_member.remove_permission!(:view_issues) @request.session[:user_id] = 9 get(:show, :params => {:id => 1}) - assert_response 403 + assert_response :forbidden end def test_show_should_deny_non_member_access_to_private_issue Issue.where(:id => 1).update_all(["is_private = ?", true]) @request.session[:user_id] = 9 get(:show, :params => {:id => 1}) - assert_response 403 + assert_response :forbidden end def test_show_should_deny_member_access_without_permission Role.find(1).remove_permission!(:view_issues) @request.session[:user_id] = 2 get(:show, :params => {:id => 1}) - assert_response 403 + assert_response :forbidden end def test_show_should_deny_member_access_to_private_issue_without_permission Issue.where(:id => 1).update_all(["is_private = ?", true]) @request.session[:user_id] = 3 get(:show, :params => {:id => 1}) - assert_response 403 + assert_response :forbidden end def test_show_should_allow_author_access_to_private_issue @@ -3158,7 +3158,7 @@ def test_show_export_to_pdf_with_changesets def test_show_invalid_should_respond_with_404 get(:show, :params => {:id => 999}) - assert_response 404 + assert_response :not_found end def test_show_on_active_project_should_display_edit_links @@ -3588,7 +3588,7 @@ def test_new_without_allowed_trackers_should_respond_with_403 role.save! @request.session[:user_id] = 2 get(:new, :params => {:project_id => 1}) - assert_response 403 + assert_response :forbidden end def test_new_without_projects_should_respond_with_403 @@ -3596,7 +3596,7 @@ def test_new_without_projects_should_respond_with_403 @request.session[:user_id] = 2 get :new - assert_response 403 + assert_response :forbidden assert_select_error /no projects/ end @@ -3604,7 +3604,7 @@ def test_new_without_enabled_trackers_on_projects_should_respond_with_403 Project.all.each {|p| p.trackers.clear} @request.session[:user_id] = 2 get :new - assert_response 403 + assert_response :forbidden assert_select_error /no projects/ end @@ -3873,7 +3873,7 @@ def test_get_new_with_no_default_status_should_display_an_error :project_id => 1 } ) - assert_response 500 + assert_response :internal_server_error assert_select_error /No default issue/ end @@ -3886,7 +3886,7 @@ def test_get_new_with_no_tracker_should_display_an_error :project_id => 1 } ) - assert_response 500 + assert_response :internal_server_error assert_select_error /No tracker/ end @@ -3898,7 +3898,7 @@ def test_new_with_invalid_project_id :project_id => 'invalid' } ) - assert_response 404 + assert_response :not_found end def test_new_with_parent_id_should_only_propose_valid_trackers @@ -4318,7 +4318,7 @@ def test_post_create_with_multi_custom_field } ) end - assert_response 302 + assert_response :found issue = Issue.order('id DESC').first assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort end @@ -4344,7 +4344,7 @@ def test_post_create_with_empty_multi_custom_field } ) end - assert_response 302 + assert_response :found issue = Issue.order('id DESC').first assert_equal [''], issue.custom_field_value(1).sort end @@ -4372,7 +4372,7 @@ def test_post_create_with_multi_user_custom_field } ) end - assert_response 302 + assert_response :found issue = Issue.order('id DESC').first assert_equal ['2', '3'], issue.custom_field_value(field).sort end @@ -4504,7 +4504,7 @@ def test_create_should_ignore_readonly_fields } } ) - assert_response 302 + assert_response :found end issue = Issue.order('id DESC').first assert_equal Date.parse('2012-07-14'), issue.start_date @@ -4530,7 +4530,7 @@ def test_create_should_ignore_unallowed_trackers } } ) - assert_response 302 + assert_response :found end assert_equal 3, issue.tracker_id end @@ -4587,7 +4587,7 @@ def test_post_create_subissue } } ) - assert_response 302 + assert_response :found end issue = Issue.order('id DESC').first assert_equal Issue.find(2), issue.parent @@ -4607,7 +4607,7 @@ def test_post_create_subissue_with_sharp_parent_id } } ) - assert_response 302 + assert_response :found end issue = Issue.order('id DESC').first assert_equal Issue.find(2), issue.parent @@ -4707,7 +4707,7 @@ def test_create_without_project_id } } ) - assert_response 302 + assert_response :found end issue = Issue.order('id DESC').first assert_equal 3, issue.project_id @@ -4747,7 +4747,7 @@ def test_create_without_project_id_should_be_denied_without_permission } } ) - assert_response 422 + assert_response :unprocessable_entity end end @@ -5041,7 +5041,7 @@ def test_post_create_should_attach_saved_attachments } } ) - assert_response 302 + assert_response :found end end @@ -5365,7 +5365,7 @@ def test_new_as_copy_with_invalid_issue_should_respond_with_404 :copy_from => 99999 } ) - assert_response 404 + assert_response :not_found end def test_create_as_copy_on_different_project @@ -6177,7 +6177,7 @@ def test_put_update_trying_to_move_issue_to_project_without_tracker_should_not_e } } ) - assert_response 302 + assert_response :found end def test_put_update_with_tracker_change @@ -6460,7 +6460,7 @@ def test_put_update_should_preserve_parent_issue_even_if_not_visible } } ) - assert_response 302 + assert_response :found assert_equal parent, issue.parent end @@ -6892,7 +6892,7 @@ def test_update_with_permission_on_tracker_should_be_allowed } } ) - assert_response 302 + assert_response :found assert_equal 'Changed subject', issue.reload.subject end @@ -6912,7 +6912,7 @@ def test_update_without_permission_on_tracker_should_be_denied } } ) - assert_response 302 + assert_response :found assert_equal 'Original subject', issue.reload.subject end @@ -6929,7 +6929,7 @@ def test_update_with_me_assigned_to_id } } ) - assert_response 302 + assert_response :found assert_equal 2, issue.reload.assigned_to_id end @@ -7279,7 +7279,7 @@ def test_bulk_update } } ) - assert_response 302 + assert_response :found # check that the issues were updated assert_equal [7, 7], Issue.where(:id =>[1, 2]).collect {|i| i.priority.id} @@ -7312,7 +7312,7 @@ def test_bulk_update_with_group_assignee } } ) - assert_response 302 + assert_response :found assert_equal [group, group], Issue.where(:id => [1, 2]).collect {|i| i.assigned_to} end end @@ -7334,7 +7334,7 @@ def test_bulk_update_on_different_projects } } ) - assert_response 302 + assert_response :found # check that the issues were updated assert_equal [7, 7, 7], Issue.find([1, 2, 6]).map(&:priority_id) @@ -7365,7 +7365,7 @@ def test_bulk_update_on_different_projects_without_rights } } ) - assert_response 403 + assert_response :forbidden assert_not_equal "Bulk should fail", Journal.last.notes end @@ -7385,7 +7385,7 @@ def test_bulk_update_should_send_a_notification } } ) - assert_response 302 + assert_response :found # 4 emails for 2 members and 2 issues # 1 email for a watcher of issue #2 assert_equal 5, ActionMailer::Base.deliveries.size @@ -7472,7 +7472,7 @@ def test_bulk_update_status } } ) - assert_response 302 + assert_response :found issue = Issue.find(1) assert issue.closed? end @@ -7542,7 +7542,7 @@ def test_bulk_update_parent_id } } ) - assert_response 302 + assert_response :found parent = Issue.find(2) assert_equal parent.id, Issue.find(1).parent_id assert_equal parent.id, Issue.find(3).parent_id @@ -7582,7 +7582,7 @@ def test_bulk_update_custom_field } } ) - assert_response 302 + assert_response :found issue = Issue.find(1) journal = issue.journals.reorder('created_on DESC').first @@ -7608,7 +7608,7 @@ def test_bulk_update_custom_field_to_blank } } ) - assert_response 302 + assert_response :found assert_equal '', Issue.find(1).custom_field_value(1) assert_equal '', Issue.find(3).custom_field_value(1) end @@ -7631,7 +7631,7 @@ def test_bulk_update_multi_custom_field } } ) - assert_response 302 + assert_response :found assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort # the custom field is not associated with the issue tracker @@ -7657,7 +7657,7 @@ def test_bulk_update_multi_custom_field_to_blank } } ) - assert_response 302 + assert_response :found assert_equal [''], Issue.find(1).custom_field_value(1) assert_equal [''], Issue.find(3).custom_field_value(1) end @@ -7676,7 +7676,7 @@ def test_bulk_update_unassign } } ) - assert_response 302 + assert_response :found # check that the issues were updated assert_nil Issue.find(2).assigned_to end @@ -7889,7 +7889,7 @@ def test_bulk_copy_without_add_issues_permission_should_be_allowed_on_project_wi :copy => '1' } ) - assert_response 302 + assert_response :found end end @@ -7906,7 +7906,7 @@ def test_bulk_copy_on_same_project_without_add_issues_permission_should_be_denie :copy => '1' } ) - assert_response 403 + assert_response :forbidden end def test_bulk_copy_on_different_project_without_add_issues_permission_should_be_denied @@ -7922,7 +7922,7 @@ def test_bulk_copy_on_different_project_without_add_issues_permission_should_be_ :copy => '1' } ) - assert_response 403 + assert_response :forbidden end def test_bulk_copy_should_allow_not_changing_the_issue_attributes @@ -8364,7 +8364,7 @@ def test_destroy_issues_with_time_entries_should_reassign_time_entries_of_issues :reassign_to_id => target.id } ) - assert_response 302 + assert_response :found assert_equal 'Successful deletion.', flash[:notice] end end @@ -8487,7 +8487,7 @@ def test_destroy_parent_and_child_issues } ) end - assert_response 302 + assert_response :found assert_equal 'Successful deletion.', flash[:notice] end @@ -8496,7 +8496,7 @@ def test_destroy_invalid_should_respond_with_404 assert_no_difference 'Issue.count' do delete(:destroy, :params => {:id => 999}) end - assert_response 404 + assert_response :not_found end def test_destroy_with_permission_on_tracker_should_be_allowed @@ -8508,7 +8508,7 @@ def test_destroy_with_permission_on_tracker_should_be_allowed assert_difference 'Issue.count', -1 do delete(:destroy, :params => {:id => issue.id}) end - assert_response 302 + assert_response :found assert_equal 'Successful deletion.', flash[:notice] end @@ -8521,7 +8521,7 @@ def test_destroy_without_permission_on_tracker_should_be_denied assert_no_difference 'Issue.count' do delete(:destroy, :params => {:id => issue.id}) end - assert_response 403 + assert_response :forbidden end def test_default_search_scope diff --git a/test/functional/issues_controller_transaction_test.rb b/test/functional/issues_controller_transaction_test.rb index 1f4e2b268c7..5f7d5ba6be1 100644 --- a/test/functional/issues_controller_transaction_test.rb +++ b/test/functional/issues_controller_transaction_test.rb @@ -246,7 +246,7 @@ def test_update_stale_issue_with_overwrite_conflict_resolution_should_update ) end - assert_response 302 + assert_response :found issue = Issue.find(1) assert_equal 4, issue.fixed_version_id journal = Journal.order('id DESC').first @@ -272,7 +272,7 @@ def test_update_stale_issue_with_add_notes_conflict_resolution_should_update ) end - assert_response 302 + assert_response :found issue = Issue.find(1) assert_nil issue.fixed_version_id journal = Journal.order('id DESC').first @@ -300,7 +300,7 @@ def test_update_stale_issue_with_add_notes_conflict_resolution_should_preserve_p ) end - assert_response 302 + assert_response :found assert_equal 'add_privates_notes_conflict_resolution', journal.notes assert_equal true, journal.private_notes assert journal.details.empty? @@ -361,7 +361,7 @@ def test_index_should_rescue_invalid_sql_query IssueQuery.any_instance.stubs(:statement).returns("INVALID STATEMENT") get :index - assert_response 500 + assert_response :internal_server_error assert_select 'p', :text => /An error occurred/ assert_nil session[:query] assert_nil session[:issues_index_sort] diff --git a/test/functional/issues_custom_fields_visibility_test.rb b/test/functional/issues_custom_fields_visibility_test.rb index 524a6dc00d6..0e971243868 100644 --- a/test/functional/issues_custom_fields_visibility_test.rb +++ b/test/functional/issues_custom_fields_visibility_test.rb @@ -300,7 +300,7 @@ def test_create_should_send_notifications_according_custom_fields_visibility } } ) - assert_response 302 + assert_response :found end assert_equal users_to_test.keys.size, ActionMailer::Base.deliveries.size @@ -341,7 +341,7 @@ def test_update_should_send_notifications_according_custom_fields_visibility } } ) - assert_response 302 + assert_response :found assert_equal users_to_test.keys.size, ActionMailer::Base.deliveries.size # tests that each user receives 1 email with the custom fields he is allowed to see only users_to_test.each do |user, fields| @@ -378,7 +378,7 @@ def test_updating_hidden_custom_fields_only_should_not_notifiy_user } } ) - assert_response 302 + assert_response :found users_to_test.each do |user, fields| mails = ActionMailer::Base.deliveries.select {|m| m.to.include? user.mail} if (fields & [@field2, @field3]).any? diff --git a/test/functional/journals_controller_test.rb b/test/functional/journals_controller_test.rb index dbd8511cf87..66887dc6297 100644 --- a/test/functional/journals_controller_test.rb +++ b/test/functional/journals_controller_test.rb @@ -43,7 +43,7 @@ def test_index_with_invalid_query_id :query_id => 999 } ) - assert_response 404 + assert_response :not_found end def test_index_should_return_privates_notes_with_permission_only @@ -156,7 +156,7 @@ def test_diff_for_custom_field_should_be_denied_if_custom_field_is_not_visible :detail_id => detail.id } ) - assert_response 302 + assert_response :found end def test_diff_should_default_to_description_diff @@ -179,7 +179,7 @@ def test_reply_to_issue def test_reply_to_issue_without_permission @request.session[:user_id] = 7 get(:new, :params => {:id => 6}, :xhr => true) - assert_response 403 + assert_response :forbidden end def test_reply_to_note @@ -224,7 +224,7 @@ def test_reply_to_private_note_should_fail_without_permission }, :xhr => true ) - assert_response 404 + assert_response :not_found end def test_edit_xhr @@ -247,7 +247,7 @@ def test_edit_private_note_should_fail_without_permission Role.find(1).remove_permission! :view_private_notes get(:edit, :params => {:id => journal.id}, :xhr => true) - assert_response 404 + assert_response :not_found end def test_update_xhr diff --git a/test/functional/mail_handler_controller_test.rb b/test/functional/mail_handler_controller_test.rb index 64b3e5dc335..3227fe5cada 100644 --- a/test/functional/mail_handler_controller_test.rb +++ b/test/functional/mail_handler_controller_test.rb @@ -49,7 +49,7 @@ def test_should_create_issue ) end end - assert_response 201 + assert_response :created end def test_should_create_issue_with_options @@ -74,7 +74,7 @@ def test_should_create_issue_with_options ) end end - assert_response 201 + assert_response :created issue = Issue.order(:id => :desc).first assert_equal true, issue.is_private end @@ -97,7 +97,7 @@ def test_should_update_issue end end end - assert_response 201 + assert_response :created end def test_should_respond_with_422_if_not_created @@ -117,7 +117,7 @@ def test_should_respond_with_422_if_not_created ) end end - assert_response 422 + assert_response :unprocessable_entity end def test_should_not_allow_with_api_disabled @@ -137,7 +137,7 @@ def test_should_not_allow_with_api_disabled ) end end - assert_response 403 + assert_response :forbidden assert_include 'Access denied', response.body end @@ -157,7 +157,7 @@ def test_should_not_allow_with_wrong_key ) end end - assert_response 403 + assert_response :forbidden assert_include 'Access denied', response.body end diff --git a/test/functional/members_controller_test.rb b/test/functional/members_controller_test.rb index 0a368e10d15..e97999f1371 100644 --- a/test/functional/members_controller_test.rb +++ b/test/functional/members_controller_test.rb @@ -207,7 +207,7 @@ def test_update_locked_member_should_be_allowed } } ) - assert_response 302 + assert_response :found member = Member.find(2) assert member.user.locked? assert_equal [1], member.role_ids diff --git a/test/functional/messages_controller_test.rb b/test/functional/messages_controller_test.rb index 85f45f1d708..12a6d5f29a6 100644 --- a/test/functional/messages_controller_test.rb +++ b/test/functional/messages_controller_test.rb @@ -81,12 +81,12 @@ def test_show_with_reply_permission def test_show_message_not_found get(:show, :params => {:board_id => 1, :id => 99999}) - assert_response 404 + assert_response :not_found end def test_show_message_from_invalid_board_should_respond_with_404 get(:show, :params => {:board_id => 999, :id => 1}) - assert_response 404 + assert_response :not_found end def test_show_should_display_watchers @@ -125,7 +125,7 @@ def test_get_new def test_get_new_with_invalid_board @request.session[:user_id] = 2 get(:new, :params => {:board_id => 99}) - assert_response 404 + assert_response :not_found end def test_post_new @@ -321,7 +321,7 @@ def test_quote_as_html_should_respond_with_404 } ) - assert_response 404 + assert_response :not_found end def test_preview_new diff --git a/test/functional/my_controller_test.rb b/test/functional/my_controller_test.rb index af3ed516bcc..da16e7c50ad 100644 --- a/test/functional/my_controller_test.rb +++ b/test/functional/my_controller_test.rb @@ -730,7 +730,7 @@ def test_add_invalid_block_should_error :block => 'invalid' } ) - assert_response 422 + assert_response :unprocessable_entity end def test_remove_block diff --git a/test/functional/news_controller_test.rb b/test/functional/news_controller_test.rb index 1a130b5131e..fbd609d1e91 100644 --- a/test/functional/news_controller_test.rb +++ b/test/functional/news_controller_test.rb @@ -44,14 +44,14 @@ def test_index_with_invalid_project_should_respond_with_404_for_logged_users @request.session[:user_id] = 2 get(:index, :params => {:project_id => 999}) - assert_response 404 + assert_response :not_found end def test_index_with_invalid_project_should_respond_with_302_for_anonymous Role.anonymous.remove_permission! :view_news with_settings :login_required => '0' do get(:index, :params => {:project_id => 999}) - assert_response 302 + assert_response :found end end @@ -60,7 +60,7 @@ def test_index_without_permission_should_fail @request.session[:user_id] = 2 get :index - assert_response 403 + assert_response :forbidden end def test_index_without_manage_news_permission_should_not_display_add_news_link @@ -107,7 +107,7 @@ def test_show_with_comments_in_reverse_order def test_show_not_found get(:show, :params => {:id => 999}) - assert_response 404 + assert_response :not_found end def test_get_new_with_project_id diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index d1de3b631ca..20cf613827b 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -744,7 +744,7 @@ def test_create_subproject_with_inherit_members_should_inherit_members } } ) - assert_response 302 + assert_response :found end project = Project.order('id desc').first assert_equal 'inherited', project.name @@ -839,7 +839,7 @@ def test_show_archived_project_should_be_denied project = Project.find_by_identifier('ecookbook') project.archive get(:show, :params => {:id => 'ecookbook'}) - assert_response 403 + assert_response :forbidden assert_select 'p', :text => /archived/ assert_not_include project.name, response.body end @@ -849,7 +849,7 @@ def test_show_archived_project_should_show_unarchive_link_to_admins project = Project.find_by_identifier('ecookbook') project.archive get(:show, :params => {:id => 'ecookbook'}) - assert_response 403 + assert_response :forbidden assert_select 'a', :text => "Unarchive" end @@ -920,13 +920,13 @@ def test_settings_should_be_denied_for_member_on_closed_project Project.find(1).close @request.session[:user_id] = 2 # manager get(:settings, :params => {:id => 1}) - assert_response 403 + assert_response :forbidden end def test_settings_should_be_denied_for_anonymous_on_closed_project Project.find(1).close get(:settings, :params => {:id => 1}) - assert_response 403 + assert_response :forbidden end def test_settings_should_accept_version_status_filter @@ -1015,7 +1015,7 @@ def test_settings_should_show_tabs_depending_on_permission role.permissions = [] role.save get(:settings, :params => {:id => project.id}) - assert_response 403 + assert_response :forbidden role.add_permission! :manage_repository, :manage_boards, :manage_project_activities get(:settings, :params => {:id => project.id}) @@ -1105,7 +1105,7 @@ def test_update_should_be_denied_for_member_on_closed_project } } ) - assert_response 403 + assert_response :forbidden assert_equal 'eCookbook', Project.find(1).name end @@ -1120,7 +1120,7 @@ def test_update_should_be_denied_for_anonymous_on_closed_project } } ) - assert_response 403 + assert_response :forbidden assert_equal 'eCookbook', Project.find(1).name end @@ -1138,7 +1138,7 @@ def test_update_child_project_without_parent_permission_should_not_show_validati } } ) - assert_response 302 + assert_response :found assert_match /Successful update/, flash[:notice] end @@ -1320,7 +1320,7 @@ def test_destroy_with_normal_user_should_not_destroy_with_subprojects :confirm => 'ecookbook' } ) - assert_response 403 + assert_response :forbidden end assert Project.find(1) end @@ -1328,7 +1328,7 @@ def test_destroy_with_normal_user_should_not_destroy_with_subprojects def test_bulk_destroy_should_require_admin @request.session[:user_id] = 2 # non-admin delete :bulk_destroy, params: { ids: [1, 2], confirm: 'Yes' } - assert_response 403 + assert_response :forbidden end def test_bulk_destroy_should_require_confirmation @@ -1338,7 +1338,7 @@ def test_bulk_destroy_should_require_confirmation end assert Project.find(1) assert Project.find(2) - assert_response 200 + assert_response :ok end def test_bulk_destroy_should_delete_projects @@ -1415,7 +1415,7 @@ def test_get_copy def test_get_copy_with_invalid_source_should_respond_with_404 @request.session[:user_id] = 1 get(:copy, :params => {:id => 99}) - assert_response 404 + assert_response :not_found end def test_get_copy_should_preselect_custom_fields diff --git a/test/functional/queries_controller_test.rb b/test/functional/queries_controller_test.rb index fa5c744b685..77560e9137f 100644 --- a/test/functional/queries_controller_test.rb +++ b/test/functional/queries_controller_test.rb @@ -34,7 +34,7 @@ def setup def test_index get :index # HTML response not implemented - assert_response 406 + assert_response :not_acceptable end def test_new_project_query @@ -62,7 +62,7 @@ def test_new_global_query def test_new_on_invalid_project @request.session[:user_id] = 2 get(:new, :params => {:project_id => 'invalid'}) - assert_response 404 + assert_response :not_found end def test_new_should_not_render_show_inline_columns_option_for_query_without_available_inline_columns @@ -359,7 +359,7 @@ def test_create_query_without_permission_should_fail } ) end - assert_response 403 + assert_response :forbidden end def test_create_global_query_without_permission_should_fail @@ -369,7 +369,7 @@ def test_create_global_query_without_permission_should_fail assert_no_difference '::Query.count' do post(:create, :params => {:query => {:name => 'Foo'}}) end - assert_response 403 + assert_response :forbidden end def test_create_global_query_from_gantt @@ -393,7 +393,7 @@ def test_create_global_query_from_gantt } } ) - assert_response 302 + assert_response :found end query = IssueQuery.order('id DESC').first assert_redirected_to "/issues/gantt?query_id=#{query.id}" @@ -424,7 +424,7 @@ def test_create_project_query_from_gantt } } ) - assert_response 302 + assert_response :found end query = IssueQuery.order('id DESC').first assert_redirected_to "/projects/ecookbook/issues/gantt?query_id=#{query.id}" @@ -445,7 +445,7 @@ def test_create_project_public_query_should_force_private_without_manage_public_ } } ) - assert_response 302 + assert_response :found end assert_not_nil query.project assert_equal Query::VISIBILITY_PRIVATE, query.visibility @@ -464,7 +464,7 @@ def test_create_global_public_query_should_force_private_without_manage_public_q } } ) - assert_response 302 + assert_response :found end assert_nil query.project assert_equal Query::VISIBILITY_PRIVATE, query.visibility @@ -482,7 +482,7 @@ def test_create_project_public_query_with_manage_public_queries_permission } } ) - assert_response 302 + assert_response :found end assert_not_nil query.project assert_equal Query::VISIBILITY_PUBLIC, query.visibility @@ -501,7 +501,7 @@ def test_create_global_public_query_should_force_private_with_manage_public_quer } } ) - assert_response 302 + assert_response :found end assert_nil query.project assert_equal Query::VISIBILITY_PRIVATE, query.visibility @@ -520,7 +520,7 @@ def test_create_global_public_query_by_admin } } ) - assert_response 302 + assert_response :found end assert_nil query.project assert_equal Query::VISIBILITY_PUBLIC, query.visibility @@ -662,7 +662,7 @@ def test_edit_sort_criteria def test_edit_invalid_query @request.session[:user_id] = 2 get(:edit, :params => {:id => 99}) - assert_response 404 + assert_response :not_found end def test_update_global_private_query diff --git a/test/functional/reports_controller_test.rb b/test/functional/reports_controller_test.rb index 9f6624f6a8c..497176b1da6 100644 --- a/test/functional/reports_controller_test.rb +++ b/test/functional/reports_controller_test.rb @@ -242,7 +242,7 @@ def test_get_issue_report_details_with_an_invalid_detail :detail => 'invalid' } ) - assert_response 404 + assert_response :not_found end def test_issue_report_details_should_csv_export diff --git a/test/functional/repositories_bazaar_controller_test.rb b/test/functional/repositories_bazaar_controller_test.rb index 36539a75f67..cf1cb52c2ca 100644 --- a/test/functional/repositories_bazaar_controller_test.rb +++ b/test/functional/repositories_bazaar_controller_test.rb @@ -291,7 +291,7 @@ def test_destroy_valid_repository } ) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end @@ -317,7 +317,7 @@ def test_destroy_invalid_repository } ) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end diff --git a/test/functional/repositories_controller_test.rb b/test/functional/repositories_controller_test.rb index f2d20e3d94f..e7306680945 100644 --- a/test/functional/repositories_controller_test.rb +++ b/test/functional/repositories_controller_test.rb @@ -93,7 +93,7 @@ def test_create } ) end - assert_response 302 + assert_response :found repository = Repository.order('id DESC').first assert_kind_of Repository::Subversion, repository assert_equal 'file:///test', repository.url @@ -138,7 +138,7 @@ def test_update } } ) - assert_response 302 + assert_response :found assert_equal 'test_update', Repository.find(11).password end @@ -162,7 +162,7 @@ def test_destroy assert_difference 'Repository.count', -1 do delete(:destroy, :params => {:id => 11}) end - assert_response 302 + assert_response :found assert_nil Repository.find_by_id(11) end @@ -279,7 +279,7 @@ def test_revisions_for_invalid_repository :repository_id => 'foo' } ) - assert_response 404 + assert_response :not_found end def test_revision @@ -523,7 +523,7 @@ def test_post_committers } } ) - assert_response 302 + assert_response :found assert_equal User.find(2), c.reload.user end end diff --git a/test/functional/repositories_cvs_controller_test.rb b/test/functional/repositories_cvs_controller_test.rb index d28f34e8e17..9c0e5052683 100644 --- a/test/functional/repositories_cvs_controller_test.rb +++ b/test/functional/repositories_cvs_controller_test.rb @@ -305,7 +305,7 @@ def test_destroy_valid_repository assert_difference 'Repository.count', -1 do delete(:destroy, :params => {:id => @repository.id}) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end @@ -327,7 +327,7 @@ def test_destroy_invalid_repository assert_difference 'Repository.count', -1 do delete(:destroy, :params => {:id => @repository.id}) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end diff --git a/test/functional/repositories_filesystem_controller_test.rb b/test/functional/repositories_filesystem_controller_test.rb index 0428ab9d1d3..54d3eea7c72 100644 --- a/test/functional/repositories_filesystem_controller_test.rb +++ b/test/functional/repositories_filesystem_controller_test.rb @@ -176,7 +176,7 @@ def test_destroy_valid_repository } ) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end @@ -198,7 +198,7 @@ def test_destroy_invalid_repository } ) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end diff --git a/test/functional/repositories_git_controller_test.rb b/test/functional/repositories_git_controller_test.rb index d20918d5a82..fee41faac40 100644 --- a/test/functional/repositories_git_controller_test.rb +++ b/test/functional/repositories_git_controller_test.rb @@ -63,7 +63,7 @@ def test_create_and_update } ) end - assert_response 302 + assert_response :found repository = Repository.order('id DESC').first assert_kind_of Repository::Git, repository assert_equal '/test', repository.url @@ -78,7 +78,7 @@ def test_create_and_update } } ) - assert_response 302 + assert_response :found repo2 = Repository.find(repository.id) assert_equal false, repo2.report_last_commit end @@ -764,7 +764,7 @@ def test_empty_revision :rev => r } ) - assert_response 404 + assert_response :not_found assert_select_error /was not found/ end end @@ -784,7 +784,7 @@ def test_destroy_valid_repository } ) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end @@ -811,7 +811,7 @@ def test_destroy_invalid_repository } ) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end diff --git a/test/functional/repositories_mercurial_controller_test.rb b/test/functional/repositories_mercurial_controller_test.rb index 52611141f37..9e0d398b12f 100644 --- a/test/functional/repositories_mercurial_controller_test.rb +++ b/test/functional/repositories_mercurial_controller_test.rb @@ -512,7 +512,7 @@ def test_annotate_not_in_tip :path => repository_path_hash(['sources', 'welcome_controller.rb'])[:param] } ) - assert_response 404 + assert_response :not_found assert_select_error /was not found/ end @@ -614,7 +614,7 @@ def test_empty_revision :rev => r } ) - assert_response 404 + assert_response :not_found assert_select_error /was not found/ end end @@ -633,7 +633,7 @@ def test_destroy_valid_repository } ) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end @@ -658,7 +658,7 @@ def test_destroy_invalid_repository } ) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end diff --git a/test/functional/repositories_subversion_controller_test.rb b/test/functional/repositories_subversion_controller_test.rb index fa49d818e6a..7b32fa1f766 100644 --- a/test/functional/repositories_subversion_controller_test.rb +++ b/test/functional/repositories_subversion_controller_test.rb @@ -414,7 +414,7 @@ def test_invalid_revision :rev => 'something_weird' } ) - assert_response 404 + assert_response :not_found assert_select_error /was not found/ end @@ -428,7 +428,7 @@ def test_invalid_revision_diff :rev_to => 'something_weird' } ) - assert_response 404 + assert_response :not_found assert_select_error /was not found/ end @@ -446,7 +446,7 @@ def test_empty_revision :rev => r } ) - assert_response 404 + assert_response :not_found assert_select_error /was not found/ end end @@ -599,7 +599,7 @@ def test_destroy_valid_repository assert_difference 'Repository.count', -1 do delete(:destroy, :params => {:id => @repository.id}) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end @@ -619,7 +619,7 @@ def test_destroy_invalid_repository assert_difference 'Repository.count', -1 do delete(:destroy, :params => {:id => @repository.id}) end - assert_response 302 + assert_response :found @project.reload assert_nil @project.repository end diff --git a/test/functional/roles_controller_test.rb b/test/functional/roles_controller_test.rb index 5d2f94dc310..0918be6f06a 100644 --- a/test/functional/roles_controller_test.rb +++ b/test/functional/roles_controller_test.rb @@ -160,7 +160,7 @@ def test_create_with_managed_roles } } ) - assert_response 302 + assert_response :found end assert_equal false, role.all_roles_managed assert_equal [2, 3], role.managed_role_ids.sort @@ -186,7 +186,7 @@ def test_edit_anonymous def test_edit_invalid_should_respond_with_404 get :edit, :params => {:id => 999} - assert_response 404 + assert_response :not_found end def test_update diff --git a/test/functional/search_controller_test.rb b/test/functional/search_controller_test.rb index 21b1fc27440..d9a397343eb 100644 --- a/test/functional/search_controller_test.rb +++ b/test/functional/search_controller_test.rb @@ -48,18 +48,18 @@ def test_search_for_projects def test_search_on_archived_project_should_return_403 Project.find(3).archive get :index, :params => {:id => 3} - assert_response 403 + assert_response :forbidden end def test_search_on_invisible_project_by_user_should_be_denied @request.session[:user_id] = 7 get :index, :params => {:id => 2} - assert_response 403 + assert_response :forbidden end def test_search_on_invisible_project_by_anonymous_user_should_redirect get :index, :params => {:id => 2} - assert_response 302 + assert_response :found end def test_search_on_private_project_by_member_should_succeed @@ -352,7 +352,7 @@ def test_search_with_pagination def test_search_with_invalid_project_id get :index, :params => {:id => 195, :q => 'recipe'} - assert_response 404 + assert_response :not_found end def test_search_should_include_closed_projects diff --git a/test/functional/settings_controller_test.rb b/test/functional/settings_controller_test.rb index cee769a16eb..3c013146ee9 100644 --- a/test/functional/settings_controller_test.rb +++ b/test/functional/settings_controller_test.rb @@ -219,7 +219,7 @@ def test_get_plugin_settings def test_get_invalid_plugin_settings get :plugin, :params => {:id => 'none'} - assert_response 404 + assert_response :not_found end def test_get_non_configurable_plugin_settings @@ -228,7 +228,7 @@ def test_get_non_configurable_plugin_settings end get :plugin, :params => {:id => 'foo'} - assert_response 404 + assert_response :not_found ensure Redmine::Plugin.unregister(:foo) @@ -274,7 +274,7 @@ def test_post_non_configurable_plugin_settings :id => 'foo', :settings => {'sample_setting' => 'Value'} } - assert_response 404 + assert_response :not_found ensure Redmine::Plugin.unregister(:foo) diff --git a/test/functional/sys_controller_test.rb b/test/functional/sys_controller_test.rb index 41986deb5ad..fb116b4d984 100644 --- a/test/functional/sys_controller_test.rb +++ b/test/functional/sys_controller_test.rb @@ -118,13 +118,13 @@ def test_fetch_changesets_one_project_by_id def test_fetch_changesets_unknown_project get :fetch_changesets, :params => {:id => 'unknown'} - assert_response 404 + assert_response :not_found end def test_disabled_ws_should_respond_with_403_error with_settings :sys_api_enabled => '0' do get :projects - assert_response 403 + assert_response :forbidden assert_include 'Access denied', response.body end end @@ -139,7 +139,7 @@ def test_api_key def test_wrong_key_should_respond_with_403_error with_settings :sys_api_enabled => 'my_secret_key' do get :projects, :params => {:key => 'wrong_key'} - assert_response 403 + assert_response :forbidden assert_include 'Access denied', response.body end end diff --git a/test/functional/timelog_controller_test.rb b/test/functional/timelog_controller_test.rb index f3ef5cbe346..464bf932772 100644 --- a/test/functional/timelog_controller_test.rb +++ b/test/functional/timelog_controller_test.rb @@ -86,7 +86,7 @@ def test_new_without_project_should_deny_without_permission @request.session[:user_id] = 3 get :new - assert_response 403 + assert_response :forbidden end def test_new_should_select_default_role_activity @@ -504,7 +504,7 @@ def test_create_without_log_time_permission_should_be_denied :hours => '7.3' } } - assert_response 403 + assert_response :forbidden end def test_create_without_project_and_issue_should_fail @@ -582,7 +582,7 @@ def test_create_without_project_should_deny_without_permission } end - assert_response 403 + assert_response :forbidden end def test_create_without_project_with_failure @@ -636,7 +636,7 @@ def test_update_should_allow_to_change_issue_to_another_project :issue_id => '5' } } - assert_response 302 + assert_response :found entry.reload assert_equal 5, entry.issue_id @@ -668,7 +668,7 @@ def test_update_should_allow_to_change_project :project_id => '2' } } - assert_response 302 + assert_response :found entry.reload assert_equal 2, entry.project_id @@ -802,7 +802,7 @@ def test_bulk_update # update time entry activity post :bulk_update, :params => {:ids => [1, 2], :time_entry => {:activity_id => 9}} - assert_response 302 + assert_response :found # check that the issues were updated assert_equal [9, 9], TimeEntry.where(:id => [1, 2]).collect {|i| i.activity_id} end @@ -823,7 +823,7 @@ def test_bulk_update_on_different_projects # update time entry activity post :bulk_update, :params => {:ids => [1, 2, 4], :time_entry => {:activity_id => 9}} - assert_response 302 + assert_response :found # check that the issues were updated assert_equal [9, 9, 9], TimeEntry.where(:id => [1, 2, 4]).collect {|i| i.activity_id} end @@ -836,7 +836,7 @@ def test_bulk_update_on_different_projects_without_rights assert ! user.allowed_to?(action, TimeEntry.find(5).project) post :bulk_update, :params => {:ids => [1, 5], :time_entry => {:activity_id => 9}} - assert_response 403 + assert_response :forbidden end def test_bulk_update_with_edit_own_time_entries_permission @@ -846,7 +846,7 @@ def test_bulk_update_with_edit_own_time_entries_permission ids = (0..1).map {TimeEntry.generate!(:user => User.find(2)).id} post :bulk_update, :params => {:ids => ids, :time_entry => {:activity_id => 9}} - assert_response 302 + assert_response :found end def test_bulk_update_with_edit_own_time_entries_permissions_should_be_denied_for_time_entries_of_other_user @@ -855,7 +855,7 @@ def test_bulk_update_with_edit_own_time_entries_permissions_should_be_denied_for Role.find_by_name('Manager').add_permission! :edit_own_time_entries post :bulk_update, :params => {:ids => [1, 2], :time_entry => {:activity_id => 9}} - assert_response 403 + assert_response :forbidden end def test_bulk_update_custom_field @@ -867,7 +867,7 @@ def test_bulk_update_custom_field :time_entry => {:custom_field_values => {'10' => '0'}} } ) - assert_response 302 + assert_response :found assert_equal ["0", "0"], TimeEntry.where(:id => [1, 2]).collect {|i| i.custom_value_for(10).value} end @@ -881,7 +881,7 @@ def test_bulk_update_clear_custom_field :time_entry => {:custom_field_values => {field.id.to_s => '__none__'}} } ) - assert_response 302 + assert_response :found assert_equal ["", ""], TimeEntry.where(:id => [1, 2]).collect {|i| i.custom_value_for(field).value} end @@ -906,7 +906,7 @@ def test_post_bulk_update_without_edit_permission_should_be_denied Role.find_by_name('Manager').remove_permission! :edit_time_entries post :bulk_update, :params => {:ids => [1, 2]} - assert_response 403 + assert_response :forbidden end def test_destroy diff --git a/test/functional/trackers_controller_test.rb b/test/functional/trackers_controller_test.rb index 196dcce1ac8..c2d2405e34c 100644 --- a/test/functional/trackers_controller_test.rb +++ b/test/functional/trackers_controller_test.rb @@ -42,7 +42,7 @@ def test_index_by_anonymous_should_redirect_to_login_form def test_index_by_user_should_respond_with_406 @request.session[:user_id] = 2 get :index - assert_response 406 + assert_response :not_acceptable end def test_new diff --git a/test/functional/users_controller_test.rb b/test/functional/users_controller_test.rb index 387e965a5c8..4302f913a9b 100644 --- a/test/functional/users_controller_test.rb +++ b/test/functional/users_controller_test.rb @@ -335,13 +335,13 @@ def test_show_should_not_fail_when_custom_values_are_nil def test_show_inactive @request.session[:user_id] = nil get :show, :params => {:id => 5} - assert_response 404 + assert_response :not_found end def test_show_inactive_by_admin @request.session[:user_id] = 1 get :show, :params => {:id => 5} - assert_response 200 + assert_response :ok assert_select 'h2', :text => /Dave2 Lopper2/ end @@ -351,7 +351,7 @@ def test_show_user_who_is_not_visible_should_return_404 @request.session[:user_id] = nil get :show, :params => {:id => user.id} - assert_response 404 + assert_response :not_found end def test_show_displays_memberships_based_on_project_visibility @@ -378,7 +378,7 @@ def test_show_displays_memberships_based_on_project_visibility def test_show_current_should_require_authentication @request.session[:user_id] = nil get :show, :params => {:id => 'current'} - assert_response 302 + assert_response :found end def test_show_current @@ -656,7 +656,7 @@ def test_edit_should_be_denied_for_anonymous get :edit, :params => {:id => 6} - assert_response 404 + assert_response :not_found end def test_edit_user_with_full_text_formatting_custom_field_should_not_fail @@ -857,7 +857,7 @@ def test_update_status_should_not_update_attributes :id => 2, :user => {:status => 3} } - assert_response 302 + assert_response :found user = User.find(2) assert_equal 3, user.status assert_equal '1', user.pref[:no_self_notified] @@ -997,7 +997,7 @@ def test_update_admin_unrelated_property_should_not_send_security_notification def test_update_should_be_denied_for_anonymous assert User.find(6).anonymous? put :update, :params => {:id => 6} - assert_response 404 + assert_response :not_found end def test_update_with_blank_email_should_not_raise_exception @@ -1051,7 +1051,7 @@ def test_destroy_should_be_denied_for_non_admin_users assert_no_difference 'User.count' do delete :destroy, :params => {:id => 2, :confirm => User.find(2).login} end - assert_response 403 + assert_response :forbidden end def test_destroy_should_be_denied_for_anonymous @@ -1059,7 +1059,7 @@ def test_destroy_should_be_denied_for_anonymous assert_no_difference 'User.count' do delete :destroy, :params => {:id => 6, :confirm => User.find(6).login} end - assert_response 404 + assert_response :not_found end def test_destroy_should_redirect_to_back_url_param @@ -1105,7 +1105,7 @@ def test_destroy_without_unsubscribe_is_denied assert_no_difference 'User.count' do delete :destroy, params: {id: user.id} end - assert_response 422 + assert_response :unprocessable_entity end end @@ -1116,7 +1116,7 @@ def test_destroy_last_admin_is_denied assert_no_difference 'User.count' do delete :destroy, params: {id: user.id} end - assert_response 422 + assert_response :unprocessable_entity end end @@ -1166,7 +1166,7 @@ def test_bulk_destroy_should_be_denied_for_non_admin_users assert_no_difference 'User.count' do delete :bulk_destroy, :params => {:ids => [2], :confirm => 'Yes'} end - assert_response 403 + assert_response :forbidden end def test_bulk_destroy_should_be_denied_for_anonymous @@ -1174,6 +1174,6 @@ def test_bulk_destroy_should_be_denied_for_anonymous assert_no_difference 'User.count' do delete :bulk_destroy, :params => {:ids => [6], :confirm => "Yes"} end - assert_response 404 + assert_response :not_found end end diff --git a/test/functional/watchers_controller_test.rb b/test/functional/watchers_controller_test.rb index 369d30b5ba0..d8719a991af 100644 --- a/test/functional/watchers_controller_test.rb +++ b/test/functional/watchers_controller_test.rb @@ -86,7 +86,7 @@ def test_watch_a_private_news_module_without_permission_should_fail assert_no_difference 'Watcher.count' do post :watch, :params => {:object_type => 'enabled_module', :object_id => m.id.to_s}, :xhr => true - assert_response 403 + assert_response :forbidden end end @@ -95,7 +95,7 @@ def test_watch_should_be_denied_without_permission @request.session[:user_id] = 3 assert_no_difference('Watcher.count') do post :watch, :params => {:object_type => 'issue', :object_id => '1'}, :xhr => true - assert_response 403 + assert_response :forbidden end end @@ -103,7 +103,7 @@ def test_watch_invalid_class_should_respond_with_404 @request.session[:user_id] = 3 assert_no_difference('Watcher.count') do post :watch, :params => {:object_type => 'foo', :object_id => '1'}, :xhr => true - assert_response 404 + assert_response :not_found end end @@ -111,7 +111,7 @@ def test_watch_invalid_object_should_respond_with_404 @request.session[:user_id] = 3 assert_no_difference('Watcher.count') do post :watch, :params => {:object_type => 'issue', :object_id => '999'}, :xhr => true - assert_response 404 + assert_response :not_found end end @@ -159,7 +159,7 @@ def test_new def test_new_as_html_should_respond_with_404 @request.session[:user_id] = 2 get :new, :params => {:object_type => 'issue', :object_id => '2'} - assert_response 404 + assert_response :not_found end def test_new_for_message @@ -581,7 +581,7 @@ def test_destroy_invalid_user_should_respond_with_404 delete :destroy, :params => { :object_type => 'issue', :object_id => '2', :user_id => '999' } - assert_response 404 + assert_response :not_found end end end diff --git a/test/functional/welcome_controller_test.rb b/test/functional/welcome_controller_test.rb index e157a0c85f3..fde599383a8 100644 --- a/test/functional/welcome_controller_test.rb +++ b/test/functional/welcome_controller_test.rb @@ -183,7 +183,7 @@ def test_unhautorized_exception_with_anonymous_should_redirect_to_login WelcomeController.any_instance.stubs(:index).raises(::Unauthorized) get :index - assert_response 302 + assert_response :found assert_redirected_to('/login?back_url='+CGI.escape('http://test.host/')) end @@ -192,6 +192,6 @@ def test_unhautorized_exception_with_anonymous_and_xmlhttprequest_should_respond @request.env["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" get :index - assert_response 401 + assert_response :unauthorized end end diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb index 31dcf395d5c..d7e9676f825 100644 --- a/test/functional/wiki_controller_test.rb +++ b/test/functional/wiki_controller_test.rb @@ -179,7 +179,7 @@ def test_show_old_version_should_not_display_section_edit_links def test_show_unexistent_page_without_edit_right get :show, :params => {:project_id => 1, :id => 'Unexistent page'} - assert_response 404 + assert_response :not_found end def test_show_unexistent_page_with_edit_right @@ -191,7 +191,7 @@ def test_show_unexistent_page_with_edit_right def test_show_specific_version_of_an_unexistent_page_without_edit_right get :show, :params => {:project_id => 1, :id => 'Unexistent page', :version => 1} - assert_response 404 + assert_response :not_found end def test_show_unexistent_page_with_parent_should_preselect_parent @@ -204,14 +204,14 @@ def test_show_unexistent_page_with_parent_should_preselect_parent def test_show_unexistent_version_page @request.session[:user_id] = 2 get :show, :params => {:project_id => 1, :id => 'CookBook_documentation', :version => 100} - assert_response 404 + assert_response :not_found end def test_show_should_not_show_history_without_permission Role.anonymous.remove_permission! :view_wiki_edits get :show, :params => {:project_id => 1, :id => 'Page with sections', :version => 2} - assert_response 302 + assert_response :found end def test_show_page_without_content_should_display_the_edit_form @@ -386,7 +386,7 @@ def test_edit_invalid_section_should_respond_with_404 @request.session[:user_id] = 2 get :edit, :params => {:project_id => 'ecookbook', :id => 'Page_with_sections', :section => 10} - assert_response 404 + assert_response :not_found end def test_update_page @@ -598,7 +598,7 @@ def test_update_page_without_content_should_create_content :id => 'NoContent', :content => {:text => 'Some content'} } - assert_response 302 + assert_response :found end end assert_equal 'Some content', page.reload.content.text @@ -780,7 +780,7 @@ def test_diff_with_invalid_version_should_respond_with_404 :project_id => 1, :id => 'CookBook_documentation', :version => '99' } - assert_response 404 + assert_response :not_found end def test_diff_with_invalid_version_from_should_respond_with_404 @@ -789,7 +789,7 @@ def test_diff_with_invalid_version_from_should_respond_with_404 :version => '99', :version_from => '98' } - assert_response 404 + assert_response :not_found end def test_annotate @@ -825,7 +825,7 @@ def test_annotate_with_invalid_version_should_respond_with_404 :project_id => 1, :id => 'CookBook_documentation', :version => '99' } - assert_response 404 + assert_response :not_found end def test_get_rename @@ -1040,7 +1040,7 @@ def test_destroy_invalid_version_should_respond_with_404 end end end - assert_response 404 + assert_response :not_found end def test_index @@ -1097,7 +1097,7 @@ def test_export_without_permission_should_be_denied Role.find_by_name('Manager').remove_permission! :export_wiki_pages get :export, :params => {:project_id => 'ecookbook'} - assert_response 403 + assert_response :forbidden end def test_date_index @@ -1110,7 +1110,7 @@ def test_date_index def test_not_found get :show, :params => {:project_id => 999} - assert_response 404 + assert_response :not_found end def test_protect_page @@ -1237,7 +1237,7 @@ def test_edit_protected_page_by_nonmember # Non members cannot edit protected wiki pages @request.session[:user_id] = 4 get :edit, :params => {:project_id => 1, :id => 'CookBook_documentation'} - assert_response 403 + assert_response :forbidden end def test_edit_protected_page_by_member @@ -1248,7 +1248,7 @@ def test_edit_protected_page_by_member def test_history_of_non_existing_page_should_return_404 get :history, :params => {:project_id => 1, :id => 'Unknown_page'} - assert_response 404 + assert_response :not_found end def test_add_attachment diff --git a/test/functional/wikis_controller_test.rb b/test/functional/wikis_controller_test.rb index 59cf9f6e82b..1f5bf894880 100644 --- a/test/functional/wikis_controller_test.rb +++ b/test/functional/wikis_controller_test.rb @@ -51,6 +51,6 @@ def test_post_destroy_should_reinitialize_empty_wiki def test_not_found @request.session[:user_id] = 1 post :destroy, :params => {:id => 999, :confirm => 1} - assert_response 404 + assert_response :not_found end end diff --git a/test/functional/workflows_controller_test.rb b/test/functional/workflows_controller_test.rb index c543ebd6b17..36fb311d9b2 100644 --- a/test/functional/workflows_controller_test.rb +++ b/test/functional/workflows_controller_test.rb @@ -158,7 +158,7 @@ def test_post_edit '3' => {'1' => {'always' => '1'}, '2' => {'always' => '1'}} } } - assert_response 302 + assert_response :found assert_equal 3, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count assert WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2).exists? @@ -175,7 +175,7 @@ def test_post_edit_with_allowed_statuses_for_new_issues '0' => {'1' => {'always' => '1'}, '2' => {'always' => '1'}} } } - assert_response 302 + assert_response :found assert WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 0, :new_status_id => 1).any? assert WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 0, :new_status_id => 2).any? @@ -195,7 +195,7 @@ def test_post_edit_with_additional_transitions '4' => {'always' => '0', 'author' => '1', 'assignee' => '1'}} } } - assert_response 302 + assert_response :found assert_equal 4, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count @@ -371,7 +371,7 @@ def test_post_permissions '3' => {'assigned_to_id' => '', 'fixed_version_id' => '', 'due_date' => ''} } } - assert_response 302 + assert_response :found workflows = WorkflowPermission.all assert_equal 3, workflows.size @@ -409,7 +409,7 @@ def test_post_copy_one_to_one :source_tracker_id => '1', :source_role_id => '2', :target_tracker_ids => ['3'], :target_role_ids => ['1'] } - assert_response 302 + assert_response :found assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 1) end @@ -420,7 +420,7 @@ def test_post_copy_one_to_many :source_tracker_id => '1', :source_role_id => '2', :target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3'] } - assert_response 302 + assert_response :found assert_equal source_transitions, status_transitions(:tracker_id => 2, :role_id => 1) assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 1) assert_equal source_transitions, status_transitions(:tracker_id => 2, :role_id => 3) @@ -435,7 +435,7 @@ def test_post_copy_many_to_many :source_tracker_id => 'any', :source_role_id => '2', :target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3'] } - assert_response 302 + assert_response :found assert_equal source_t2, status_transitions(:tracker_id => 2, :role_id => 1) assert_equal source_t3, status_transitions(:tracker_id => 3, :role_id => 1) assert_equal source_t2, status_transitions(:tracker_id => 2, :role_id => 3) @@ -448,7 +448,7 @@ def test_post_copy_with_incomplete_source_specification_should_fail :source_tracker_id => '', :source_role_id => '2', :target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3'] } - assert_response 200 + assert_response :ok assert_select 'div.flash.error', :text => 'Please select a source tracker or role' end end @@ -459,7 +459,7 @@ def test_post_copy_with_incomplete_target_specification_should_fail :source_tracker_id => '1', :source_role_id => '2', :target_tracker_ids => ['2', '3'] } - assert_response 200 + assert_response :ok assert_select 'div.flash.error', :text => 'Please select target tracker(s) and role(s)' end end diff --git a/test/integration/account_test.rb b/test/integration/account_test.rb index 302fe665cc2..47dee79bc55 100644 --- a/test/integration/account_test.rb +++ b/test/integration/account_test.rb @@ -97,7 +97,7 @@ def test_autologin_should_use_autologin_cookie_name :autologin => 1 } ) - assert_response 302 + assert_response :found end assert cookies['custom_autologin'].present? token = cookies['custom_autologin'] diff --git a/test/integration/api_test/api_test.rb b/test/integration/api_test/api_test.rb index d8ab172a370..d076e81eb43 100644 --- a/test/integration/api_test/api_test.rb +++ b/test/integration/api_test/api_test.rb @@ -35,7 +35,7 @@ def test_api_should_work_with_protect_from_forgery }, :headers => credentials('admin') ) - assert_response 201 + assert_response :created end ensure ActionController::Base.allow_forgery_protection = false diff --git a/test/integration/api_test/attachments_test.rb b/test/integration/api_test/attachments_test.rb index 2c918b080c7..4bb40a3021d 100644 --- a/test/integration/api_test/attachments_test.rb +++ b/test/integration/api_test/attachments_test.rb @@ -61,7 +61,7 @@ def teardown test "GET /attachments/:id.xml should deny access without credentials" do get '/attachments/7.xml' - assert_response 401 + assert_response :unauthorized end test "GET /attachments/download/:id/:filename should return the attachment content" do @@ -72,7 +72,7 @@ def teardown test "GET /attachments/download/:id/:filename should deny access without credentials" do get '/attachments/download/7/archive.zip' - assert_response 401 + assert_response :unauthorized end test "GET /attachments/thumbnail/:id should return the thumbnail" do @@ -118,7 +118,7 @@ def teardown :params => {:attachment => {:filename => '', :description => 'updated'}}, :headers => credentials('jsmith') ) - assert_response 422 + assert_response :unprocessable_entity assert_equal 'application/json', response.media_type json = ActiveSupport::JSON.decode(response.body) assert_include "File cannot be blank", json['errors'] @@ -209,7 +209,7 @@ def teardown "CONTENT_TYPE" => 'image/png' }.merge(credentials('jsmith')) ) - assert_response 406 + assert_response :not_acceptable end end @@ -224,7 +224,7 @@ def teardown "CONTENT_TYPE" => 'application/octet-stream' }.merge(credentials('jsmith')) ) - assert_response 422 + assert_response :unprocessable_entity assert_select 'error', :text => /exceeds the maximum allowed file size/ end end diff --git a/test/integration/api_test/authentication_test.rb b/test/integration/api_test/authentication_test.rb index 56e918c9d53..aeb5fed1580 100644 --- a/test/integration/api_test/authentication_test.rb +++ b/test/integration/api_test/authentication_test.rb @@ -28,7 +28,7 @@ def teardown def test_api_should_deny_without_credentials get '/users/current.xml' - assert_response 401 + assert_response :unauthorized assert response.headers.has_key?('WWW-Authenticate') end @@ -37,7 +37,7 @@ def test_api_should_accept_http_basic_auth_using_username_and_password user.password = 'my_password' end get '/users/current.xml', :headers => credentials(user.login, 'my_password') - assert_response 200 + assert_response :ok end def test_api_should_deny_http_basic_auth_using_username_and_wrong_password @@ -45,7 +45,7 @@ def test_api_should_deny_http_basic_auth_using_username_and_wrong_password user.password = 'my_password' end get '/users/current.xml', :headers => credentials(user.login, 'wrong_password') - assert_response 401 + assert_response :unauthorized end def test_api_should_deny_http_basic_auth_if_twofa_is_active @@ -54,61 +54,61 @@ def test_api_should_deny_http_basic_auth_if_twofa_is_active user.update(twofa_scheme: 'totp') end get '/users/current.xml', :headers => credentials(user.login, 'my_password') - assert_response 401 + assert_response :unauthorized end def test_api_should_accept_http_basic_auth_using_api_key user = User.generate! token = Token.create!(:user => user, :action => 'api') get '/users/current.xml', :headers => credentials(token.value, 'X') - assert_response 200 + assert_response :ok end def test_api_should_deny_http_basic_auth_using_wrong_api_key user = User.generate! token = Token.create!(:user => user, :action => 'feeds') # not the API key get '/users/current.xml', :headers => credentials(token.value, 'X') - assert_response 401 + assert_response :unauthorized end def test_api_should_accept_auth_using_api_key_as_parameter user = User.generate! token = Token.create!(:user => user, :action => 'api') get "/users/current.xml?key=#{token.value}" - assert_response 200 + assert_response :ok end def test_api_should_deny_auth_using_wrong_api_key_as_parameter user = User.generate! token = Token.create!(:user => user, :action => 'feeds') # not the API key get "/users/current.xml?key=#{token.value}" - assert_response 401 + assert_response :unauthorized end def test_api_should_accept_auth_using_api_key_as_request_header user = User.generate! token = Token.create!(:user => user, :action => 'api') get "/users/current.xml", :headers => {'X-Redmine-API-Key' => token.value.to_s} - assert_response 200 + assert_response :ok end def test_api_should_deny_auth_using_wrong_api_key_as_request_header user = User.generate! token = Token.create!(:user => user, :action => 'feeds') # not the API key get "/users/current.xml", :headers => {'X-Redmine-API-Key' => token.value.to_s} - assert_response 401 + assert_response :unauthorized end def test_api_should_trigger_basic_http_auth_with_basic_authorization_header ApplicationController.any_instance.expects(:authenticate_with_http_basic).once get '/users/current.xml', :headers => credentials('jsmith') - assert_response 401 + assert_response :unauthorized end def test_api_should_not_trigger_basic_http_auth_with_non_basic_authorization_header ApplicationController.any_instance.expects(:authenticate_with_http_basic).never get '/users/current.xml', :headers => {'HTTP_AUTHORIZATION' => 'Digest foo bar'} - assert_response 401 + assert_response :unauthorized end def test_invalid_utf8_credentials_should_not_trigger_an_error @@ -126,7 +126,7 @@ def test_api_request_should_not_use_user_session assert_response :success get '/users/current.json' - assert_response 401 + assert_response :unauthorized end def test_api_should_accept_switch_user_header_for_admin_user @@ -140,7 +140,7 @@ def test_api_should_accept_switch_user_header_for_admin_user def test_api_should_respond_with_412_when_trying_to_switch_to_a_invalid_user get '/users/current', :headers => {'X-Redmine-API-Key' => User.find(1).api_key, 'X-Redmine-Switch-User' => 'foobar'} - assert_response 412 + assert_response :precondition_failed end def test_api_should_respond_with_412_when_trying_to_switch_to_a_locked_user @@ -148,7 +148,7 @@ def test_api_should_respond_with_412_when_trying_to_switch_to_a_locked_user assert user.locked? get '/users/current', :headers => {'X-Redmine-API-Key' => User.find(1).api_key, 'X-Redmine-Switch-User' => user.login} - assert_response 412 + assert_response :precondition_failed end def test_api_should_not_accept_switch_user_header_for_non_admin_user diff --git a/test/integration/api_test/enumerations_test.rb b/test/integration/api_test/enumerations_test.rb index 41756dc38c3..c47dc83fe2c 100644 --- a/test/integration/api_test/enumerations_test.rb +++ b/test/integration/api_test/enumerations_test.rb @@ -42,7 +42,7 @@ class Redmine::ApiTest::EnumerationsTest < Redmine::ApiTest::Base test "GET /enumerations/invalid_subclass.xml should return 404" do get '/enumerations/invalid_subclass.xml' - assert_response 404 + assert_response :not_found assert_equal 'application/xml', response.media_type end end diff --git a/test/integration/api_test/groups_test.rb b/test/integration/api_test/groups_test.rb index b293d96b647..8e57d8352ed 100644 --- a/test/integration/api_test/groups_test.rb +++ b/test/integration/api_test/groups_test.rb @@ -24,7 +24,7 @@ class Redmine::ApiTest::GroupsTest < Redmine::ApiTest::Base test "GET /groups.xml should require authentication" do get '/groups.xml' - assert_response 401 + assert_response :unauthorized end test "GET /groups.xml should return givable groups" do @@ -61,7 +61,7 @@ class Redmine::ApiTest::GroupsTest < Redmine::ApiTest::Base test "GET /groups.json should require authentication" do get '/groups.json' - assert_response 401 + assert_response :unauthorized end test "GET /groups.json should return groups" do diff --git a/test/integration/api_test/issues_test.rb b/test/integration/api_test/issues_test.rb index 485f0513721..05d40647c2a 100644 --- a/test/integration/api_test/issues_test.rb +++ b/test/integration/api_test/issues_test.rb @@ -723,7 +723,7 @@ def test_show_should_include_issue_attributes '/issues.json', :params => {:issue => {:project_id => 999, :subject => "API"}}, :headers => credentials('jsmith')) - assert_response 422 + assert_response :unprocessable_entity end test "POST /issues.json with invalid project_id and any assigned_to_id should respond with 422" do @@ -737,7 +737,7 @@ def test_show_should_include_issue_attributes } }, :headers => credentials('jsmith')) - assert_response 422 + assert_response :unprocessable_entity end test "POST /issues.json with invalid project_id and any fixed_version_id should respond with 422" do @@ -751,7 +751,7 @@ def test_show_should_include_issue_attributes } }, :headers => credentials('jsmith')) - assert_response 422 + assert_response :unprocessable_entity end test "PUT /issues/:id.xml" do diff --git a/test/integration/api_test/time_entries_test.rb b/test/integration/api_test/time_entries_test.rb index bc8b5c4a154..f2c38d80bc9 100644 --- a/test/integration/api_test/time_entries_test.rb +++ b/test/integration/api_test/time_entries_test.rb @@ -63,7 +63,7 @@ class Redmine::ApiTest::TimeEntriesTest < Redmine::ApiTest::Base test "GET /time_entries/:id.xml with invalid id should 404" do get '/time_entries/999.xml', :headers => credentials('jsmith') - assert_response 404 + assert_response :not_found end test "POST /time_entries.xml with issue_id should create time entry" do @@ -211,7 +211,7 @@ class Redmine::ApiTest::TimeEntriesTest < Redmine::ApiTest::Base '/time_entries/2.xml', :params => {:time_entry => {:hours => '2.3', :comments => 'API Update'}}, :headers => credentials('dlopper')) - assert_response 403 + assert_response :forbidden end test "DELETE /time_entries/:id.xml should destroy time entry" do diff --git a/test/integration/api_test/users_test.rb b/test/integration/api_test/users_test.rb index a05fe1ee3dd..183dd3af9aa 100644 --- a/test/integration/api_test/users_test.rb +++ b/test/integration/api_test/users_test.rb @@ -261,7 +261,7 @@ class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base test "GET /users/current.xml should require authentication" do get '/users/current.xml' - assert_response 401 + assert_response :unauthorized end test "GET /users/current.xml should return current user" do diff --git a/test/integration/api_test/wiki_pages_test.rb b/test/integration/api_test/wiki_pages_test.rb index a871d809f9d..2aa60304cd6 100644 --- a/test/integration/api_test/wiki_pages_test.rb +++ b/test/integration/api_test/wiki_pages_test.rb @@ -26,7 +26,7 @@ class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base test "GET /projects/:project_id/wiki/index.xml should return wiki pages" do get '/projects/ecookbook/wiki/index.xml' - assert_response 200 + assert_response :ok assert_equal 'application/xml', response.media_type assert_select 'wiki_pages[type=array]' do assert_select 'wiki_page', :count => Wiki.find(1).pages.count @@ -45,7 +45,7 @@ class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base test "GET /projects/:project_id/wiki/:title.xml should return wiki page" do get '/projects/ecookbook/wiki/CookBook_documentation.xml' - assert_response 200 + assert_response :ok assert_equal 'application/xml', response.media_type assert_select 'wiki_page' do assert_select 'title', :text => 'CookBook_documentation' @@ -60,7 +60,7 @@ class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base test "GET /projects/:project_id/wiki/:title.xml?include=attachments should include attachments" do get '/projects/ecookbook/wiki/Page_with_an_inline_image.xml?include=attachments' - assert_response 200 + assert_response :ok assert_equal 'application/xml', response.media_type assert_select 'wiki_page' do assert_select 'title', :text => 'Page_with_an_inline_image' @@ -75,13 +75,13 @@ class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base test "GET /projects/:project_id/wiki/:title.xml with unknown title and edit permission should respond with 404" do get '/projects/ecookbook/wiki/Invalid_Page.xml', :headers => credentials('jsmith') - assert_response 404 + assert_response :not_found assert_equal 'application/xml', response.media_type end test "GET /projects/:project_id/wiki/:title/:version.xml should return wiki page version" do get '/projects/ecookbook/wiki/CookBook_documentation/2.xml' - assert_response 200 + assert_response :ok assert_equal 'application/xml', response.media_type assert_select 'wiki_page' do assert_select 'title', :text => 'CookBook_documentation' @@ -98,7 +98,7 @@ class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base Role.anonymous.remove_permission! :view_wiki_edits get '/projects/ecookbook/wiki/CookBook_documentation/2.xml' - assert_response 401 + assert_response :unauthorized assert_equal 'application/xml', response.media_type end @@ -130,7 +130,7 @@ class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base WikiContentVersion.find_by_id(2).update(author_id: nil) get '/projects/ecookbook/wiki/CookBook_documentation/2.xml' - assert_response 200 + assert_response :ok assert_equal 'application/xml', response.media_type assert_select 'wiki_page' do assert_select 'author', 0 @@ -176,7 +176,7 @@ class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base }, :headers => credentials('jsmith') ) - assert_response 409 + assert_response :conflict end end end @@ -194,7 +194,7 @@ class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base }, :headers => credentials('jsmith') ) - assert_response 201 + assert_response :created end end @@ -227,7 +227,7 @@ class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base }, :headers => credentials('jsmith') ) - assert_response 201 + assert_response :created end end @@ -251,7 +251,7 @@ class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base }, :headers => credentials('jsmith') ) - assert_response 201 + assert_response :created end end diff --git a/test/integration/application_test.rb b/test/integration/application_test.rb index aa33cb095c6..7f077b57174 100644 --- a/test/integration/application_test.rb +++ b/test/integration/application_test.rb @@ -57,23 +57,23 @@ def test_set_localization def test_token_based_access_should_not_start_session # issue of a private project get '/issues/4.atom' - assert_response 302 + assert_response :found atom_key = User.find(2).atom_key get "/issues/4.atom?key=#{atom_key}" - assert_response 200 + assert_response :ok assert_nil session[:user_id] end def test_missing_template_should_respond_with_4xx get '/login.png' - assert_response 406 + assert_response :not_acceptable end def test_invalid_token_should_call_custom_handler ActionController::Base.allow_forgery_protection = true post '/issues' - assert_response 422 + assert_response :unprocessable_entity assert_include "Invalid form authenticity token.", response.body ensure ActionController::Base.allow_forgery_protection = false @@ -83,7 +83,7 @@ def test_localization_should_be_set_correctly_on_invalid_token ActionController::Base.allow_forgery_protection = true Setting.default_language = 'en' post '/issues', :headers => {'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'} - assert_response 422 + assert_response :unprocessable_entity assert_equal :fr, current_language assert_select "html[lang=?]", "fr" ensure @@ -93,7 +93,7 @@ def test_localization_should_be_set_correctly_on_invalid_token def test_require_login_with_pdf_format_should_not_error with_settings :login_required => '1' do get '/issues/1.pdf' - assert_response 302 + assert_response :found end end @@ -101,7 +101,7 @@ def test_find_optional_project_should_not_error Role.anonymous.remove_permission! :view_gantt with_settings :login_required => '0' do get '/projects/nonexistingproject/issues/gantt' - assert_response 302 + assert_response :found end end @@ -109,6 +109,6 @@ def test_find_optional_project_should_render_404_for_logged_users log_user('jsmith', 'jsmith') get '/projects/nonexistingproject/issues/gantt' - assert_response 404 + assert_response :not_found end end diff --git a/test/integration/attachments_test.rb b/test/integration/attachments_test.rb index 09027d89517..910ec6b2cbc 100644 --- a/test/integration/attachments_test.rb +++ b/test/integration/attachments_test.rb @@ -75,7 +75,7 @@ def test_upload_as_js_and_attach_to_an_issue } } ) - assert_response 302 + assert_response :found end issue = Issue.order('id DESC').first @@ -159,7 +159,7 @@ def test_upload_and_resubmit_after_validation_failure } } ) - assert_response 302 + assert_response :found end issue = Issue.order('id DESC').first @@ -185,7 +185,7 @@ def test_upload_filename_with_plus :attachments => {'p0' => {:filename => filename, :token => token}} } ) - assert_response 302 + assert_response :found end issue = Issue.order('id DESC').first assert_equal 'Issue with upload', issue.subject @@ -258,7 +258,7 @@ def test_download_all_for_journal_should_check_visibility with_settings :login_required => '0' do get "/attachments/journals/3/download" - assert_response 403 + assert_response :forbidden end with_settings :login_required => '1' do get "/attachments/journals/3/download" diff --git a/test/integration/issues_test.rb b/test/integration/issues_test.rb index d69b0f052be..fca3d3981a5 100644 --- a/test/integration/issues_test.rb +++ b/test/integration/issues_test.rb @@ -87,7 +87,7 @@ def test_create_issue_by_anonymous_without_permission_should_fail } ) end - assert_response 302 + assert_response :found end def test_create_issue_by_anonymous_with_custom_permission_should_succeed @@ -104,7 +104,7 @@ def test_create_issue_by_anonymous_with_custom_permission_should_succeed } } ) - assert_response 302 + assert_response :found end assert_equal User.anonymous, issue.author end @@ -341,7 +341,7 @@ def test_issue_with_user_custom_field } } ) - assert_response 302 + assert_response :found end # Issue view @@ -381,11 +381,11 @@ def test_update_using_invalid_http_verbs subject = 'Updated by an invalid http verb' get '/issues/update/1', :params => {:issue => {:subject => subject}} - assert_response 404 + assert_response :not_found assert_not_equal subject, Issue.find(1).subject post '/issues/1', :params => {:issue => {:subject => subject}} - assert_response 404 + assert_response :not_found assert_not_equal subject, Issue.find(1).subject end @@ -394,7 +394,7 @@ def test_get_watch_should_be_invalid assert_no_difference 'Watcher.count' do get '/watchers/watch?object_type=issue&object_id=1' - assert_response 404 + assert_response :not_found end end @@ -406,6 +406,6 @@ def test_invalid_operators_should_render_404 'v' => {'cf_9' => ['2021-05-25']} } - assert_response 404 + assert_response :not_found end end diff --git a/test/integration/lib/redmine/field_format/attachment_format_test.rb b/test/integration/lib/redmine/field_format/attachment_format_test.rb index 68de8e155f3..0d3590ff40c 100644 --- a/test/integration/lib/redmine/field_format/attachment_format_test.rb +++ b/test/integration/lib/redmine/field_format/attachment_format_test.rb @@ -68,7 +68,7 @@ def test_create_with_attachment } } ) - assert_response 302 + assert_response :found end end @@ -108,7 +108,7 @@ def test_create_without_attachment } } ) - assert_response 302 + assert_response :found end end @@ -166,7 +166,7 @@ def test_failure_on_create_should_preserve_attachment } } ) - assert_response 302 + assert_response :found end end @@ -193,7 +193,7 @@ def test_create_with_valid_extension } } ) - assert_response 302 + assert_response :found end end end diff --git a/test/integration/projects_test.rb b/test/integration/projects_test.rb index 4e436737116..04125323030 100644 --- a/test/integration/projects_test.rb +++ b/test/integration/projects_test.rb @@ -33,9 +33,9 @@ def test_archive_project assert !Project.find(1).active? get '/projects/1' - assert_response 403 + assert_response :forbidden get "/projects/#{subproject.id}" - assert_response 403 + assert_response :forbidden post "/projects/1/unarchive" assert_redirected_to "/admin/projects" @@ -49,7 +49,7 @@ def test_modules_should_not_allow_get assert_no_difference 'EnabledModule.count' do get '/projects/1/modules', :params => {:enabled_module_names => ['']} - assert_response 404 + assert_response :not_found end end end diff --git a/test/integration/sessions_test.rb b/test/integration/sessions_test.rb index c297cd502b9..e34184cb728 100644 --- a/test/integration/sessions_test.rb +++ b/test/integration/sessions_test.rb @@ -38,7 +38,7 @@ def test_change_password_kills_sessions jsmith.save! get '/my/account' - assert_response 302 + assert_response :found assert flash[:error].include?('Your session has expired') end @@ -50,7 +50,7 @@ def test_lock_user_kills_sessions assert jsmith.activate! get '/my/account' - assert_response 302 + assert_response :found assert flash[:error].include?('Your session has expired') end @@ -62,7 +62,7 @@ def test_update_user_does_not_kill_sessions jsmith.save! get '/my/account' - assert_response 200 + assert_response :ok end def test_change_password_generates_a_new_token_for_current_session @@ -70,7 +70,7 @@ def test_change_password_generates_a_new_token_for_current_session assert_not_nil token = session[:tk] get '/my/password' - assert_response 200 + assert_response :ok post( '/my/password', :params => { @@ -79,11 +79,11 @@ def test_change_password_generates_a_new_token_for_current_session :new_password_confirmation => 'secret123' } ) - assert_response 302 + assert_response :found assert_not_equal token, session[:tk] get '/my/account' - assert_response 200 + assert_response :ok end def test_simultaneous_sessions_should_be_valid diff --git a/test/integration/sudo_mode_test.rb b/test/integration/sudo_mode_test.rb index 07a4d9e9e44..68a312b8337 100644 --- a/test/integration/sudo_mode_test.rb +++ b/test/integration/sudo_mode_test.rb @@ -28,7 +28,7 @@ def test_sudo_mode_should_be_active_after_login } } ) - assert_response 302 + assert_response :found user = User.find_by_login("psmith") assert_kind_of User, user @@ -68,7 +68,7 @@ def test_add_user :sudo_password => 'admin' } ) - assert_response 302 + assert_response :found user = User.find_by_login("psmith") assert_kind_of User, user diff --git a/test/integration/users_test.rb b/test/integration/users_test.rb index 46b0032e07c..35672e0534f 100644 --- a/test/integration/users_test.rb +++ b/test/integration/users_test.rb @@ -27,7 +27,7 @@ def test_destroy_should_not_accept_get_requests assert_no_difference 'User.count' do get '/users/destroy/2' - assert_response 404 + assert_response :not_found end end end From bd4ac7c96c590d08c865908de2cf82f3e5640f96 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Sat, 18 May 2024 06:17:51 +0000 Subject: [PATCH 031/459] Fix RuboCop offense Rails/WhereRange (#39889). git-svn-id: https://svn.redmine.org/redmine/trunk@22838 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/nested_set/issue_nested_set.rb | 2 +- lib/redmine/nested_set/project_nested_set.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/redmine/nested_set/issue_nested_set.rb b/lib/redmine/nested_set/issue_nested_set.rb index 8655ee325e0..1b775c3bbff 100644 --- a/lib/redmine/nested_set/issue_nested_set.rb +++ b/lib/redmine/nested_set/issue_nested_set.rb @@ -38,7 +38,7 @@ def self.included(base) def target_lft scope_for_max_rgt = self.class.where(:root_id => root_id).where(:parent_id => parent_id) if id - scope_for_max_rgt = scope_for_max_rgt.where("id < ?", id) + scope_for_max_rgt = scope_for_max_rgt.where(id: ...id) end max_rgt = scope_for_max_rgt.maximum(:rgt) if max_rgt diff --git a/lib/redmine/nested_set/project_nested_set.rb b/lib/redmine/nested_set/project_nested_set.rb index c3a095888f6..e34f9adf4f4 100644 --- a/lib/redmine/nested_set/project_nested_set.rb +++ b/lib/redmine/nested_set/project_nested_set.rb @@ -40,7 +40,7 @@ def self.included(base) def target_lft siblings_rgt = - self.class.where(:parent_id => parent_id).where("name < ?", name).maximum(:rgt) + self.class.where(:parent_id => parent_id).where(name: ...name).maximum(:rgt) if siblings_rgt siblings_rgt + 1 elsif parent_id From d584e7248c865b4b93a674bc360478768b620f2c Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Sat, 18 May 2024 06:20:25 +0000 Subject: [PATCH 032/459] Update RuboCop Rails to 2.25 (#39889). git-svn-id: https://svn.redmine.org/redmine/trunk@22839 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index c42714d5775..f4e8c5a08f7 100644 --- a/Gemfile +++ b/Gemfile @@ -108,7 +108,7 @@ group :test do # RuboCop gem 'rubocop', '~> 1.63.0', require: false gem 'rubocop-performance', '~> 1.21.0', require: false - gem 'rubocop-rails', '~> 2.24.0', require: false + gem 'rubocop-rails', '~> 2.25.0', require: false end local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") From c0af36b12da1d053d87735c174e7c79e97254e75 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Sun, 19 May 2024 05:07:42 +0000 Subject: [PATCH 033/459] Dynamic generation of supported code highlighting languages in help section (#40681). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22840 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/help_controller.rb | 1 + .../code_highlighting_languages.html.erb | 889 +----------------- test/functional/help_controller_test.rb | 8 + 3 files changed, 18 insertions(+), 880 deletions(-) diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index f085e18da07..766781afecc 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -30,6 +30,7 @@ def show_wiki_syntax end def show_code_highlighting + @available_lexers = Rouge::Lexer.all.sort_by(&:tag) render template: "help/wiki_syntax/code_highlighting_languages", layout: nil end end diff --git a/app/views/help/wiki_syntax/code_highlighting_languages.html.erb b/app/views/help/wiki_syntax/code_highlighting_languages.html.erb index 57ae458889d..8e15e105156 100644 --- a/app/views/help/wiki_syntax/code_highlighting_languages.html.erb +++ b/app/views/help/wiki_syntax/code_highlighting_languages.html.erb @@ -14,886 +14,15 @@ Language Description - - abap - SAP - Advanced Business Application Programming - - - actionscript - ActionScript [aliases: as,as3] - - - ada - The Ada 2012 programming language - - - apache - configuration files for Apache web server - - - apex - The Apex programming language (provided by salesforce) - - - apiblueprint - Markdown based API description language. [aliases: apiblueprint,apib] - - - applescript - The AppleScript scripting language by Apple Inc. (https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html) [aliases: applescript] - - - armasm - Arm assembly syntax - - - augeas - The Augeas programming language (augeas.net) [aliases: aug] - - - awk - pattern-directed scanning and processing language - - - batchfile - Windows Batch File [aliases: bat,batch,dosbatch,winbatch] - - - bbcbasic - BBC BASIC syntax - - - bibtex - BibTeX [aliases: bib] - - - biml - BIML, Business Intelligence Markup Language - - - bpf - BPF bytecode syntax - - - brainfuck - The Brainfuck programming language - - - brightscript - BrightScript Programming Language (https://developer.roku.com/en-ca/docs/references/brightscript/language/brightscript-language-reference.md) [aliases: bs,brs] - - - bsl - The 1C:Enterprise programming language - - - c - The C programming language - - - ceylon - Say more, more clearly. - - - cfscript - CFScript, the CFML scripting language [aliases: cfc] - - - cisco_ios - Cisco IOS configuration lexer - - - clean - The Clean programming language (clean.cs.ru.nl) - - - clojure - The Clojure programming language (clojure.org) [aliases: clj,cljs] - - - cmake - The cross-platform, open-source build system - - - cmhg - RISC OS C module header generator source file - - - codeowners - Code Owners syntax (https://docs.gitlab.com/ee/user/project/codeowners/reference.html) - - - coffeescript - The Coffeescript programming language (coffeescript.org) [aliases: coffee,coffee-script] - - - common_lisp - The Common Lisp variant of Lisp (common-lisp.net) [aliases: cl,common-lisp,elisp,emacs-lisp,lisp] - - - conf - A generic lexer for configuration files [aliases: config,configuration] - - - console - A generic lexer for shell sessions. Accepts ?lang and ?output lexer options, a ?prompt option, ?comments to enable # comments, and ?error to handle error messages. [aliases: terminal,shell_session,shell-session] - - - coq - Coq (coq.inria.fr) - - - cpp - The C++ programming language [aliases: c++] - - - crystal - Crystal The Programming Language (crystal-lang.org) [aliases: cr] - - - csharp - a multi-paradigm language targeting .NET [aliases: c#,cs] - - - css - Cascading Style Sheets, used to style web pages - - - csvs - The CSV Schema Language (digital-preservation.github.io) - - - cuda - Compute Unified Device Architecture, used for programming with NVIDIA GPU - - - cypher - The Cypher query language (neo4j.com/docs/cypher-manual) [aliases: cypher] - - - cython - Cython and Pyrex source code (cython.org) [aliases: pyx,pyrex] - - - d - The D programming language(dlang.org) [aliases: dlang] - - - dafny - The Dafny programming language (github.com/dafny-lang/dafny) - - - dart - The Dart programming language (dart.dev) - - - datastudio - Datastudio scripting language - - - diff - Lexes unified diffs or patches [aliases: patch,udiff] - - - digdag - A simple, open source, multi-cloud workflow engine (https://www.digdag.io/) - - - docker - Dockerfile syntax [aliases: dockerfile,Dockerfile] - - - dot - graph description language [aliases: graphviz] - - - ecl - Enterprise Control Language (hpccsystems.com) - - - eex - Embedded Elixir [aliases: leex,heex] - - - eiffel - Eiffel programming language - - - elixir - Elixir language (elixir-lang.org) [aliases: elixir,exs] - - - elm - The Elm programming language (http://elm-lang.org/) - - - email - An email message [aliases: eml,e-mail] - - - epp - Embedded Puppet template files - - - erb - Embedded ruby template files [aliases: eruby,rhtml] - - - erlang - The Erlang programming language (erlang.org) [aliases: erl] - - - escape - A generic lexer for including escaped content - see Formatter.enable_escape! [aliases: esc] - - - factor - Factor, the practical stack language (factorcode.org) - - - fluent - Fluent localization files [aliases: ftl] - - - fortran - Fortran 2008 (free-form) - - - freefem - The FreeFEM programming language (freefem.org) [aliases: ff] - - - fsharp - F# (fsharp.net) - - - gdscript - The Godot Engine programming language (https://godotengine.org/) [aliases: gd,gdscript] - - - ghc-cmm - GHC Cmm is the intermediate representation of the GHC Haskell compiler [aliases: cmm] - - - ghc-core - Intermediate representation of the GHC Haskell compiler. - - - gherkin - A business-readable spec DSL (github.com/cucumber/cucumber/wiki/Gherkin) [aliases: cucumber,behat] - - - glsl - The GLSL shader language - - - go - The Go programming language (http://golang.org) [aliases: go,golang] - - - gradle - A powerful build system for the JVM - - - graphql - GraphQL - - - groovy - The Groovy programming language (http://www.groovy-lang.org/) - - - hack - The Hack programming language (hacklang.org) [aliases: hack,hh] - - - haml - The Haml templating system for Ruby (haml.info) [aliases: HAML] - - - handlebars - the Handlebars and Mustache templating languages [aliases: hbs,mustache] - - - haskell - The Haskell programming language (haskell.org) [aliases: hs] - - - haxe - Haxe Cross-platform Toolkit (http://haxe.org) [aliases: hx,haxe] - - - hcl - Hashicorp Configuration Language, used by Terraform and other Hashicorp tools - - - hlsl - HLSL, the High Level Shading Language for DirectX (docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl) - - - hocon - Human-Optimized Config Object Notation (https://github.com/lightbend/config) - - - hql - Hive Query Language SQL dialect - - - html - HTML, the markup language of the web - - - http - http requests and responses - - - hylang - The HyLang programming language (hylang.org) [aliases: hy] - - - idlang - Interactive Data Language - - - idris - The Idris programming language (idris-lang.org) [aliases: idr] - - - igorpro - WaveMetrics Igor Pro - - - ini - the INI configuration format - - - io - The IO programming language (http://iolanguage.com) - - - irb - Shell sessions in IRB or Pry [aliases: pry] - - - irb_output - - - - isabelle - Isabelle theories (isabelle.in.tum.de) [aliases: isa,Isabelle] - - - isbl - The ISBL programming language - - - j - The J programming language (jsoftware.com) - - - janet - The Janet programming language (janet-lang.org) [aliases: jdn] - - - java - The Java programming language (java.com) - - - javascript - JavaScript, the browser scripting language [aliases: js] - - - jinja - Django/Jinja template engine (jinja.pocoo.org) [aliases: django] - - - jsl - The JMP Scripting Language (JSL) (jmp.com) - - - json - JavaScript Object Notation (json.org) - - - json-doc - JavaScript Object Notation with extensions for documentation [aliases: jsonc] - - - jsonnet - An elegant, formally-specified config language for JSON - - - jsp - JSP - - - jsx - An XML-like syntax extension to JavaScript (facebook.github.io/jsx/) [aliases: jsx,react] - - - julia - The Julia programming language [aliases: jl] - - - kotlin - Kotlin Programming Language (http://kotlinlang.org) - - - lasso - The Lasso programming language (lassosoft.com) [aliases: lassoscript] - - - lean - The Lean programming language (leanprover.github.io) [aliases: lean] - - - liquid - Liquid is a templating engine for Ruby (liquidmarkup.org) - - - literate_coffeescript - Literate coffeescript [aliases: litcoffee] - - - literate_haskell - Literate haskell [aliases: lithaskell,lhaskell,lhs] - - - livescript - LiveScript, a language which compiles to JavaScript (livescript.net) [aliases: ls] - - - llvm - The LLVM Compiler Infrastructure (http://llvm.org/) - - - lua - Lua (http://www.lua.org) - - - lustre - The Lustre programming language (Verimag) - - - lutin - The Lutin programming language (Verimag) - - - m68k - Motorola 68k Assembler - - - magik - Smallworld Magik - - - make - Makefile syntax [aliases: makefile,mf,gnumake,bsdmake] - - - markdown - Markdown, a light-weight markup language for authors [aliases: md,mkd] - - - mason - The HTML::Mason framework (https://metacpan.org/pod/HTML::Mason) - - - mathematica - Wolfram Mathematica, the world's definitive system for modern technical computing. [aliases: wl] - - - matlab - Matlab [aliases: m] - - - meson - Meson's specification language (mesonbuild.com) - - - minizinc - MiniZinc is a free and open-source constraint modeling language (minizinc.org) - - - moonscript - Moonscript (http://www.moonscript.org) [aliases: moon] - - - mosel - An optimization language used by Fico's Xpress. - - - msgtrans - RISC OS message translator messages file - - - mxml - MXML - - - nasm - Netwide Assembler - - - nesasm - Nesasm3 assembly (6502 asm) [aliases: nes] - - - nginx - configuration files for the nginx web server (nginx.org) - - - nial - The Nial programming language (nial-array-language.org) - - - nim - The Nim programming language (http://nim-lang.org/) [aliases: nimrod] - - - nix - The Nix expression language (https://nixos.org/nix/manual/#ch-expression-language) [aliases: nixos] - - - objective_c - an extension of C commonly used to write Apple software [aliases: objc,obj-c,obj_c,objectivec] - - - objective_cpp - an extension of C++ uncommonly used to write Apple software [aliases: objcpp,obj-cpp,obj_cpp,objectivecpp,objc++,obj-c++,obj_c++,objectivec++] - - - ocaml - Objective Caml (ocaml.org) - - - ocl - OMG Object Constraint Language (omg.org/spec/OCL) [aliases: OCL] - - - openedge - The OpenEdge ABL programming language [aliases: abl] - - - opentype_feature_file - Feature specifications for an OpenType font (adobe-type-tools.github.io/afdko) [aliases: fea,opentype,opentypefeature] - - - pascal - a procedural programming language commonly used as a teaching language. - - - perl - The Perl scripting language (perl.org) [aliases: pl] - - - php - The PHP scripting language (php.net) [aliases: php,php3,php4,php5] - - - plaintext - A boring lexer that doesn't highlight anything [aliases: text] - - - plist - plist [aliases: plist] - - - plsql - Procedural Language Structured Query Language for Oracle relational database - - - pony - - - - postscript - The PostScript language (adobe.com/devnet/postscript.html) [aliases: postscr,postscript,ps,eps] - - - powershell - powershell [aliases: posh,microsoftshell,msshell] - - - praat - The Praat scripting language (praat.org) - - - prolog - The Prolog programming language (http://en.wikipedia.org/wiki/Prolog) [aliases: prolog] - - - prometheus - prometheus [aliases: prometheus] - - - properties - .properties config files for Java - - - protobuf - Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data [aliases: proto] - - - puppet - The Puppet configuration management language (puppetlabs.org) [aliases: pp] - - - python - The Python programming language (python.org) [aliases: py] - - - q - The Q programming language (kx.com) [aliases: kdb+] - - - qml - QML, a UI markup language [aliases: qml] - - - r - The R statistics language (r-project.org) [aliases: r,R,s,S] - - - racket - Racket is a Lisp descended from Scheme (racket-lang.org) - - - reasonml - New syntax on top of OCaml ecosystem (reasonml.github.io) - - - rego - The Rego open-policy-agent (OPA) policy language (openpolicyagent.org) - - - rescript - The ReScript programming language (rescript-lang.org) - - - rml - A system agnostic domain-specific language for runtime monitoring and verification (https://rmlatdibris.github.io/) - - - robot_framework - Robot Framework is a generic open source automation testing framework (robotframework.org) [aliases: robot,robot-framework] - - - ruby - The Ruby programming language (ruby-lang.org) [aliases: rb] - - - rust - The Rust programming language (rust-lang.org) [aliases: rs,rust,no_run,rs,no_run,rust,ignore,rs,ignore,rust,should_panic,rs,should_panic] - - - sas - SAS (Statistical Analysis Software) - - - sass - The Sass stylesheet language language (sass-lang.com) - - - scala - The Scala programming language (scala-lang.org) [aliases: scala] - - - scheme - The Scheme variant of Lisp - - - scss - SCSS stylesheets (sass-lang.com) - - - sed - sed, the ultimate stream editor - - - shell - Various shell languages, including sh and bash [aliases: bash,zsh,ksh,sh] - - - sieve - mail filtering language - - - slice - Specification Language for Ice (doc.zeroc.com) - - - slim - The Slim template language - - - smalltalk - The Smalltalk programming language [aliases: st,squeak] - - - smarty - Smarty Template Engine [aliases: smarty] - - - sml - Standard ML [aliases: ml] - - - sparql - Semantic Query Language, for RDF data - - - sqf - Status Quo Function, a Real Virtuality engine scripting language - - - sql - Structured Query Language, for relational databases - - - ssh - A lexer for SSH configuration files - - - stan - Stan Modeling Language (mc-stan.org) - - - stata - The Stata programming language (www.stata.com) - - - supercollider - A cross-platform interpreted programming language for sound synthesis, algorithmic composition, and realtime performance - - - svelte - Svelte single-file components (https://svelte.dev/) - - - swift - Multi paradigm, compiled programming language developed by Apple for iOS and OS X development. (developer.apple.com/swift) - - - systemd - A lexer for systemd unit files [aliases: unit-file] - - - syzlang - Syscall description language used by syzkaller - - - syzprog - Program description language used by syzkaller - - - tap - Test Anything Protocol [aliases: tap] - - - tcl - The Tool Command Language (tcl.tk) - - - terraform - Terraform HCL Interpolations [aliases: tf] - - - tex - The TeX typesetting system [aliases: TeX,LaTeX,latex] - - - toml - the TOML configuration format (https://github.com/toml-lang/toml) - - - tsx - TypeScript-compatible JSX (www.typescriptlang.org/docs/handbook/jsx.html) - - - ttcn3 - The TTCN3 programming language (ttcn-3.org) - - - tulip - the tulip programming language (twitter.com/tuliplang) [aliases: tulip] - - - turtle - Terse RDF Triple Language, TriG - - - twig - Twig template engine (twig.sensiolabs.org) - - - typescript - TypeScript, a superset of JavaScript (https://www.typescriptlang.org/) [aliases: ts] - - - vala - A programming language similar to csharp. - - - vb - Visual Basic [aliases: visualbasic] - - - vcl - The configuration language for Varnish HTTP Cache (varnish-cache.org) [aliases: varnishconf,varnish] - - - velocity - Velocity is a Java-based template engine (velocity.apache.org) - - - verilog - The System Verilog hardware description language - - - vhdl - Very High Speed Integrated Circuit Hardware Description Language - - - viml - VimL, the scripting language for the Vim editor (vim.org) [aliases: vim,vimscript,ex] - - - vue - Vue.js single-file components [aliases: vuejs] - - - wollok - Wollok lang - - - xml - <desc for="this-lexer">XML</desc> - - - xojo - Xojo [aliases: realbasic] - - - xpath - XML Path Language (XPath) 3.1 - - - xquery - XQuery 3.1: An XML Query Language - - - yaml - Yaml Ain't Markup Language (yaml.org) [aliases: yml] - - - yang - Lexer for the YANG 1.1 modeling language (RFC7950) - - - zig - The Zig programming language (ziglang.org) [aliases: zir] - + <% @available_lexers.each do |lexer| %> + + <%= lexer.tag %> + + <%= lexer.desc %> + <%= " [aliases: #{lexer.aliases.uniq.join(', ')}]" if lexer.aliases.any? %> + + + <% end %> diff --git a/test/functional/help_controller_test.rb b/test/functional/help_controller_test.rb index c988ce7f0c6..153a6d5184a 100644 --- a/test/functional/help_controller_test.rb +++ b/test/functional/help_controller_test.rb @@ -87,5 +87,13 @@ def test_get_help_code_highlighting assert_response :success assert_select 'h1', :text => "List of languages supported by Redmine code highlighter" + + # 1-based index + 1 for the header row + index = Rouge::Lexer.all.sort_by(&:tag).index(Rouge::Lexers::Ruby) + 2 + assert_select "table tr:nth-of-type(#{index})" do + assert_select '>td:nth-of-type(1)', :text => 'ruby' + assert_select '>td:nth-of-type(2)', :text => /The Ruby programming language/ + assert_select '>td:nth-of-type(2)', :text => /\[aliases: rb\]/ + end end end From 107fe074b2b7b0556a67ac7f1f203501f32617b7 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Tue, 21 May 2024 09:01:30 +0000 Subject: [PATCH 034/459] Relax rouge version dependency in Gemfile (#36594). Contributed by Holger Just (@hjust). git-svn-id: https://svn.redmine.org/redmine/trunk@22841 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index f4e8c5a08f7..5188aec6a85 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ source 'https://rubygems.org' ruby '>= 3.0.0', '< 3.4.0' gem 'rails', '7.1.2' -gem 'rouge', '~> 4.2.0' +gem 'rouge', '~> 4.2' gem 'mini_mime', '~> 1.1.0' gem "actionpack-xml_parser" gem 'roadie-rails', '~> 3.2.0' From b42d7984b1cc2530488d136ea215dfc59984ee44 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Thu, 23 May 2024 11:25:16 +0000 Subject: [PATCH 035/459] Fix RuboCop offense Style/SuperArguments (#39887). git-svn-id: https://svn.redmine.org/redmine/trunk@22842 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/application_helper.rb | 2 +- app/models/mailer.rb | 4 ++-- app/models/project.rb | 2 +- app/models/project_custom_field.rb | 2 +- app/models/repository/cvs.rb | 2 +- app/models/version.rb | 2 +- app/models/wiki_page.rb | 4 ++-- config/initializers/10-patches.rb | 2 +- lib/redmine/export/csv.rb | 2 +- lib/redmine/export/pdf.rb | 2 +- lib/redmine/wiki_formatting/common_mark/markdown_filter.rb | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 910f1f431db..1dd96cbadf8 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1689,7 +1689,7 @@ def image_tag(source, options={}) elsif current_theme && current_theme.images.include?(source) source = current_theme.image_path(source) end - super(source, options) + super end # Overrides Rails' javascript_include_tag with plugins support diff --git a/app/models/mailer.rb b/app/models/mailer.rb index 716482ec3f6..ddbc7b39416 100644 --- a/app/models/mailer.rb +++ b/app/models/mailer.rb @@ -53,7 +53,7 @@ def process(action, *args) lang ||= Setting.default_language set_language_if_valid(lang) - super(action, *args) + super ensure User.current = initial_user ::I18n.locale = initial_language @@ -714,7 +714,7 @@ def mail(headers={}, &block) end if block - super(headers, &block) + super else super(headers) do |format| format.text diff --git a/app/models/project.rb b/app/models/project.rb index 909080a112d..09927b4cc56 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -902,7 +902,7 @@ def safe_attributes=(attrs, user=User.current) attrs['custom_fields'].reject! {|c| !editable_custom_field_ids.include?(c['id'].to_s)} end - super(attrs, user) + super end # Returns an auto-generated project identifier based on the last identifier used diff --git a/app/models/project_custom_field.rb b/app/models/project_custom_field.rb index be2892b56fc..6c11b225f14 100644 --- a/app/models/project_custom_field.rb +++ b/app/models/project_custom_field.rb @@ -28,6 +28,6 @@ def visible_by?(project, user=User.current) def visibility_by_project_condition(project_key=nil, user=User.current, id_column=nil) project_key ||= "#{Project.table_name}.id" - super(project_key, user, id_column) + super end end diff --git a/app/models/repository/cvs.rb b/app/models/repository/cvs.rb index 532f8b32865..6797c1893cf 100644 --- a/app/models/repository/cvs.rb +++ b/app/models/repository/cvs.rb @@ -204,7 +204,7 @@ def fetch_changesets # Overrides Repository#validate_repository_path to validate # against root_url attribute. def validate_repository_path(attribute=:root_url) - super(attribute) + super end private diff --git a/app/models/version.rb b/app/models/version.rb index ec1a9f77b53..937ec9221c7 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -187,7 +187,7 @@ def safe_attributes=(attrs, user=User.current) attrs['custom_fields'].reject! {|c| !editable_custom_field_ids.include?(c['id'].to_s)} end - super(attrs, user) + super end # Returns true if +user+ or current user is allowed to view the version diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index 4f7e55c3909..cf23612c0f1 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -108,7 +108,7 @@ def safe_attributes=(attrs, user=User.current) end end - super(attrs, user) + super end # Manages redirects if page is renamed or moved @@ -210,7 +210,7 @@ def editable_by?(usr) end def attachments_deletable?(usr=User.current) - editable_by?(usr) && super(usr) + editable_by?(usr) && super end def parent_title diff --git a/config/initializers/10-patches.rb b/config/initializers/10-patches.rb index 20d442add88..df8afc291b4 100644 --- a/config/initializers/10-patches.rb +++ b/config/initializers/10-patches.rb @@ -98,7 +98,7 @@ def formats=(values) if (Array(values) & [:xml, :json]).any? values << :api end - super(values) + super end end) end diff --git a/lib/redmine/export/csv.rb b/lib/redmine/export/csv.rb index 9e0f23c5c22..8e56b38f33c 100644 --- a/lib/redmine/export/csv.rb +++ b/lib/redmine/export/csv.rb @@ -57,7 +57,7 @@ def <<(row) field end end - super(row) + super end end end diff --git a/lib/redmine/export/pdf.rb b/lib/redmine/export/pdf.rb index a0aeec0c97e..acb09bdce44 100644 --- a/lib/redmine/export/pdf.rb +++ b/lib/redmine/export/pdf.rb @@ -57,7 +57,7 @@ def SetFont(family, style='', size=0, fontfile='') style.delete!('I') if family.to_s.casecmp('dejavusans') == 0 && current_language.to_s.casecmp("vi") != 0 # DejaVuSansMono Italic Arabic font has problem style.delete!('I') if family.to_s.casecmp('dejavusansmono') == 0 - super(family, style, size, fontfile) + super end alias_method :set_font, :SetFont diff --git a/lib/redmine/wiki_formatting/common_mark/markdown_filter.rb b/lib/redmine/wiki_formatting/common_mark/markdown_filter.rb index 8b28c2e95fd..916c8883c4e 100644 --- a/lib/redmine/wiki_formatting/common_mark/markdown_filter.rb +++ b/lib/redmine/wiki_formatting/common_mark/markdown_filter.rb @@ -27,7 +27,7 @@ module CommonMark # options class MarkdownFilter < HTML::Pipeline::TextFilter def initialize(text, context = nil, result = nil) - super(text, context, result) + super @text = @text.delete "\r" end From 81e0a932386f172ec9fad6ba2e2261fb4375076b Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Thu, 23 May 2024 11:31:45 +0000 Subject: [PATCH 036/459] Update RuboCop to 1.64 (#39887). git-svn-id: https://svn.redmine.org/redmine/trunk@22843 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .rubocop_todo.yml | 2 +- Gemfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 015c61dd878..51845adb240 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --exclude-limit 20 --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.63.0. +# using RuboCop version 1.64.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new diff --git a/Gemfile b/Gemfile index 5188aec6a85..101ee94e31d 100644 --- a/Gemfile +++ b/Gemfile @@ -106,7 +106,7 @@ group :test do gem "capybara", ">= 3.39" gem 'selenium-webdriver', '>= 4.11.0' # RuboCop - gem 'rubocop', '~> 1.63.0', require: false + gem 'rubocop', '~> 1.64.0', require: false gem 'rubocop-performance', '~> 1.21.0', require: false gem 'rubocop-rails', '~> 2.25.0', require: false end From 9293b72a4515fd7780561dc402c9bbc3e04a944c Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Fri, 24 May 2024 02:16:23 +0000 Subject: [PATCH 037/459] Add tests for current alt attribute behavior in images (#40650). Patch by Katsuya HIDAKA (@hidakatsuya). git-svn-id: https://svn.redmine.org/redmine/trunk@22844 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/helpers/application_helper_test.rb | 33 +++++++++++++++++++ .../common_mark/application_helper_test.rb | 28 ++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/test/helpers/application_helper_test.rb b/test/helpers/application_helper_test.rb index cdbad8bc841..443ad4698d6 100644 --- a/test/helpers/application_helper_test.rb +++ b/test/helpers/application_helper_test.rb @@ -198,6 +198,39 @@ def test_attached_images end end + def test_attached_image_alt_attribute_with_textile + attachments = Attachment.all + with_settings text_formatting: 'textile' do + # When alt text is set + assert_match %r[This is a logo], + textilizable('!logo.gif(alt text)!', attachments: attachments) + + # When alt text and style are set + assert_match %r[This is a logo], + textilizable('!{width:100px}logo.gif(alt text)!', attachments: attachments) + + # When alt text is not set + assert_match %r[This is a logo], + textilizable('!logo.gif!', attachments: attachments) + + # When alt text is not set and the attachment has no description + assert_match %r[], + textilizable('!testfile.PNG!', attachments: attachments) + + # When no matching attachments are found + assert_match %r[], + textilizable('!no-match.jpg!', attachments: attachments) + assert_match %r[alt text], + textilizable('!no-match.jpg(alt text)!', attachments: attachments) + + # When no attachment is registered + assert_match %r[], + textilizable('!logo.gif!', attachments: []) + assert_match %r[alt text], + textilizable('!logo.gif(alt text)!', attachments: []) + end + end + def test_attached_images_on_issue issue = Issue.generate! attachment_1 = Attachment.generate!(:file => mock_file_with_options(:original_filename => "attached_on_issue.png"), :container => issue) diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb index b5c79335be8..c198f64cd60 100644 --- a/test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb +++ b/test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb @@ -62,5 +62,33 @@ def test_toc_with_markdown_formatting_should_be_parsed end end + def test_attached_image_alt_attribute_with_madkrown + attachments = Attachment.all + with_settings text_formatting: 'common_mark' do + # When alt text is set + assert_match %r[alt text], + textilizable('![alt text](logo.gif)', attachments: attachments) + + # When alt text is not set + assert_match %r[This is a logo], + textilizable('![](logo.gif)', attachments: attachments) + + # When alt text is not set and the attachment has no description + assert_match %r[], + textilizable('![](testfile.PNG)', attachments: attachments) + + # When no matching attachments are found + assert_match %r[], + textilizable('![](no-match.jpg)', attachments: attachments) + assert_match %r[alt text], + textilizable('![alt text](no-match.jpg)', attachments: attachments) + + # When no attachment is registered + assert_match %r[], + textilizable('![](logo.gif)', attachments: []) + assert_match %r[alt text], + textilizable('![alt text](logo.gif)', attachments: []) + end + end end end From c9fda88a407034405c1116e81fd29ebd1524c9f9 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Fri, 24 May 2024 02:52:32 +0000 Subject: [PATCH 038/459] Fix duplicated alt and title attributes for attached images in Textile formatter (#40650). Patch by Katsuya HIDAKA (@hidakatsuya). git-svn-id: https://svn.redmine.org/redmine/trunk@22845 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/application_helper.rb | 23 +++++++++++++++++------ test/helpers/application_helper_test.rb | 4 ++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1dd96cbadf8..37bfcf0de9c 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -944,16 +944,27 @@ def parse_inline_attachments(text, project, obj, attr, only_path, options) attachments += obj.attachments if obj.respond_to?(:attachments) end if attachments.present? - text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png|webp))"(\s+alt="([^"]*)")?/i) do |m| - filename, ext, alt, alttext = $1, $2, $3, $4 + title_and_alt_re = /\s+(title|alt)="([^"]*)"/i + + text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png|webp))"([^>]*)/i) do |m| + filename, ext, other_attrs = $1, $2, $3 + # search for the picture in attachments if found = Attachment.latest_attach(attachments, CGI.unescape(filename)) image_url = download_named_attachment_url(found, found.filename, :only_path => only_path) desc = found.description.to_s.delete('"') - if !desc.blank? && alttext.blank? - alt = " title=\"#{desc}\" alt=\"#{desc}\"" - end - "src=\"#{image_url}\"#{alt} loading=\"lazy\"" + + # remove title and alt attributes after extracting them + title_and_alt = other_attrs.scan(title_and_alt_re).to_h + other_attrs.gsub!(title_and_alt_re, '') + + title_and_alt_attrs = if !desc.blank? && title_and_alt['alt'].blank? + " title=\"#{desc}\" alt=\"#{desc}\"" + else + # restore original title and alt attributes + " #{title_and_alt.map { |k, v| %[#{k}="#{v}"] }.join(' ')}" + end + "src=\"#{image_url}\"#{title_and_alt_attrs} loading=\"lazy\"#{other_attrs}" else m end diff --git a/test/helpers/application_helper_test.rb b/test/helpers/application_helper_test.rb index 443ad4698d6..70c11273284 100644 --- a/test/helpers/application_helper_test.rb +++ b/test/helpers/application_helper_test.rb @@ -202,11 +202,11 @@ def test_attached_image_alt_attribute_with_textile attachments = Attachment.all with_settings text_formatting: 'textile' do # When alt text is set - assert_match %r[This is a logo], + assert_match %r[alt text], textilizable('!logo.gif(alt text)!', attachments: attachments) # When alt text and style are set - assert_match %r[This is a logo], + assert_match %r[alt text], textilizable('!{width:100px}logo.gif(alt text)!', attachments: attachments) # When alt text is not set From a4e7d34cb7582910a2c8f512c31220873404cbaa Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Mon, 27 May 2024 07:41:57 +0000 Subject: [PATCH 039/459] Add `updated_on` and `updated_by` fields to Issues API journal response (#40449). Contributed by Thomas Hoffmann (@ThomasHo). git-svn-id: https://svn.redmine.org/redmine/trunk@22846 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/issues/show.api.rsb | 2 ++ test/integration/api_test/issues_test.rb | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/views/issues/show.api.rsb b/app/views/issues/show.api.rsb index 6f23ca4b474..2c341163ae1 100644 --- a/app/views/issues/show.api.rsb +++ b/app/views/issues/show.api.rsb @@ -59,6 +59,8 @@ api.issue do api.user(:id => journal.user_id, :name => journal.user.name) unless journal.user.nil? api.notes journal.notes api.created_on journal.created_on + api.updated_on journal.updated_on + api.updated_by(:id => journal.updated_by.id, :name => journal.updated_by.name) unless journal.updated_by.nil? api.private_notes journal.private_notes api.array :details do journal.visible_details.each do |detail| diff --git a/test/integration/api_test/issues_test.rb b/test/integration/api_test/issues_test.rb index 05d40647c2a..142dc86b834 100644 --- a/test/integration/api_test/issues_test.rb +++ b/test/integration/api_test/issues_test.rb @@ -242,6 +242,8 @@ def test_index_should_allow_timestamp_filtering assert_select 'issue journals[type=array]' do assert_select 'journal[id="1"]' do + assert_select 'updated_on', :text => Issue.find(1).journals[0].updated_on.iso8601 + assert_select 'updated_by[id="1"][name="Redmine Admin"]' assert_select 'private_notes', :text => 'false' assert_select 'details[type=array]' do assert_select 'detail[name=status_id]' do From 6a4abab8ce00b5b0cb6e0a161bfedf3366393308 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Mon, 27 May 2024 14:26:16 +0000 Subject: [PATCH 040/459] Add timeout for thumbnail generation process (#37530). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22847 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/configuration.yml.example | 4 ++++ lib/redmine/configuration.rb | 3 ++- lib/redmine/thumbnail.rb | 17 +++++++++++++++-- test/unit/attachment_test.rb | 19 +++++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/config/configuration.yml.example b/config/configuration.yml.example index ac127a4b5e4..c528d764e07 100644 --- a/config/configuration.yml.example +++ b/config/configuration.yml.example @@ -178,6 +178,10 @@ default: # the `gs` binary. Used to generate attachment thumbnails of PDF files. #gs_command: + # Timeout when generating thumbnails using the `convert` or `gs` command. + # Timeout is set in seconds. + #thumbnails_generation_timeout: 10 + # Configuration of MiniMagick font. # # Redmine uses MiniMagick in order to export a gantt chart to a PNG image. diff --git a/lib/redmine/configuration.rb b/lib/redmine/configuration.rb index 00b76cbc178..4fdd2918408 100644 --- a/lib/redmine/configuration.rb +++ b/lib/redmine/configuration.rb @@ -27,7 +27,8 @@ module Configuration 'avatar_server_url' => 'https://www.gravatar.com', 'email_delivery' => nil, 'max_concurrent_ajax_uploads' => 2, - 'common_mark_enable_hardbreaks' => true + 'common_mark_enable_hardbreaks' => true, + 'thumbnails_generation_timeout' => 10 } @config = nil diff --git a/lib/redmine/thumbnail.rb b/lib/redmine/thumbnail.rb index 4c886a5b3ec..6a0729411f4 100644 --- a/lib/redmine/thumbnail.rb +++ b/lib/redmine/thumbnail.rb @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'fileutils' +require 'timeout' module Redmine module Thumbnail @@ -51,8 +52,20 @@ def self.generate(source, target, size, is_pdf = false) else cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -auto-orient -thumbnail #{shell_quote size_option} #{shell_quote target}" end - unless system(cmd) - logger.error("Creating thumbnail failed (#{$?}):\nCommand: #{cmd}") + + pid = nil + begin + Timeout.timeout(Redmine::Configuration['thumbnails_generation_timeout'].to_i) do + pid = Process.spawn(cmd) + _, status = Process.wait2(pid) + unless status.success? + logger.error("Creating thumbnail failed (#{status.exitstatus}):\nCommand: #{cmd}") + return nil + end + end + rescue Timeout::Error + Process.kill('KILL', pid) + logger.error("Creating thumbnail timed out:\nCommand: #{cmd}") return nil end end diff --git a/test/unit/attachment_test.rb b/test/unit/attachment_test.rb index 2e37672ab2b..b88350fbac9 100644 --- a/test/unit/attachment_test.rb +++ b/test/unit/attachment_test.rb @@ -626,6 +626,25 @@ def test_thumbnail_should_be_at_least_of_requested_size ensure set_tmp_attachments_directory end + + def test_thumbnail_should_timeout + dummy_pid = 37530 + Process.stubs(:spawn).returns(dummy_pid) + Process.stubs(:wait2).raises(Timeout::Error) + Process.stubs(:kill).returns(1) + Process.stubs(:wait).returns(dummy_pid) + Rails.logger.expects(:error).with(regexp_matches(/Creating thumbnail timed out/)) + + set_fixtures_attachments_directory + Attachment.clear_thumbnails + + attachment = Attachment.find(16) + thumbnail = attachment.thumbnail + + assert_nil thumbnail + ensure + set_tmp_attachments_directory + end else puts '(ImageMagick convert not available)' end From 3acc94914f21b65c3ae98e0e358802b561b53ae3 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Tue, 28 May 2024 17:40:09 +0000 Subject: [PATCH 041/459] Link "Last activity" column to project activity page (#40706, #23954). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22848 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/helpers/projects_queries_helper.rb | 10 ++++++++++ test/functional/projects_controller_test.rb | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/helpers/projects_queries_helper.rb b/app/helpers/projects_queries_helper.rb index dc540a432b3..66e47d551eb 100644 --- a/app/helpers/projects_queries_helper.rb +++ b/app/helpers/projects_queries_helper.rb @@ -40,6 +40,16 @@ def column_value(column, item, value) get_project_status_label[column.value_object(item)] when :parent_id link_to_project(item.parent) unless item.parent.nil? + when :last_activity_date + formatted_value = super + if value.present? && formatted_value.present? + link_to( + formatted_value, + project_activity_path(item, :from => User.current.time_to_date(value)) + ) + else + formatted_value + end else super end diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 20cf613827b..a21b50b077b 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -260,7 +260,10 @@ def test_index_with_last_activity_date_column assert_response :success end assert_equal ['Name', 'Description', 'Last activity'], columns_in_list - assert_select 'tr#project-1 td.last_activity_date', :text => format_time(Journal.find(3).created_on) + activity_time = Journal.find(3).created_on + assert_select "tr#project-1 td.last_activity_date a[href=?]", + project_activity_path(Project.find(1), :from => User.current.time_to_date(activity_time)), + :text => format_time(activity_time) assert_select 'tr#project-4 td.last_activity_date', :text => '' end From a73eb69648cb8f35dd5519c64a200949de9b18ac Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 29 May 2024 15:06:28 +0000 Subject: [PATCH 042/459] Introduce configuration for done ratio options interval (#31756). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22849 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/issue_statuses/_form.html.erb | 2 +- app/views/issues/_attributes.html.erb | 2 +- app/views/issues/bulk_edit.html.erb | 2 +- app/views/settings/_issues.html.erb | 2 ++ app/views/settings/_repositories.html.erb | 2 +- config/locales/en.yml | 1 + config/settings.yml | 3 +++ test/functional/issues_controller_test.rb | 15 +++++++++++++++ 8 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/views/issue_statuses/_form.html.erb b/app/views/issue_statuses/_form.html.erb index 8f06451c69e..c2487b00291 100644 --- a/app/views/issue_statuses/_form.html.erb +++ b/app/views/issue_statuses/_form.html.erb @@ -4,7 +4,7 @@

<%= f.text_field :name, :required => true %>

<%= f.text_area :description, :rows => 4 %>

<% if Issue.use_status_for_done_ratio? %> -

<%= f.select :default_done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }), :include_blank => true, :label => :field_done_ratio %>

+

<%= f.select :default_done_ratio, ((0..100).step(Setting.issue_done_ratio_interval.to_i).to_a.collect {|r| ["#{r} %", r]}), :include_blank => true, :label => :field_done_ratio %>

<% end %>

<%= f.check_box :is_closed %>

diff --git a/app/views/issues/_attributes.html.erb b/app/views/issues/_attributes.html.erb index 40b89547ab2..517b67f95eb 100644 --- a/app/views/issues/_attributes.html.erb +++ b/app/views/issues/_attributes.html.erb @@ -88,7 +88,7 @@ <% end %> <% if @issue.safe_attribute?('done_ratio') && Issue.use_field_for_done_ratio? %> -

<%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }), :required => @issue.required_attribute?('done_ratio') %>

+

<%= f.select :done_ratio, ((0..100).step(Setting.issue_done_ratio_interval.to_i).to_a.collect {|r| ["#{r} %", r]}), :required => @issue.required_attribute?('done_ratio') %>

<% end %> diff --git a/app/views/issues/bulk_edit.html.erb b/app/views/issues/bulk_edit.html.erb index 4fe457b32eb..a379305be74 100644 --- a/app/views/issues/bulk_edit.html.erb +++ b/app/views/issues/bulk_edit.html.erb @@ -178,7 +178,7 @@ <% if @safe_attributes.include?('done_ratio') && Issue.use_field_for_done_ratio? %>

- <%= select_tag 'issue[done_ratio]', options_for_select([[l(:label_no_change_option), '']] + (0..10).to_a.collect {|r| ["#{r*10} %", r*10] }, @issue_params[:done_ratio]) %> + <%= select_tag 'issue[done_ratio]', options_for_select([[l(:label_no_change_option), '']] + (0..100).step(Setting.issue_done_ratio_interval.to_i).to_a.collect {|r| ["#{r} %", r]}, @issue_params[:done_ratio]) %>

<% end %> diff --git a/app/views/settings/_issues.html.erb b/app/views/settings/_issues.html.erb index 68f9a1d7b5b..7532d5d0e1b 100644 --- a/app/views/settings/_issues.html.erb +++ b/app/views/settings/_issues.html.erb @@ -17,6 +17,8 @@

<%= setting_select :issue_done_ratio, Issue::DONE_RATIO_OPTIONS.collect {|i| [l("setting_issue_done_ratio_#{i}"), i]} %>

+

<%= setting_select :issue_done_ratio_interval, [5, 10].collect {|i| ["#{i} %", i]} %>

+

<%= setting_multiselect :non_working_week_days, (1..7).map {|d| [day_name(d), d.to_s]}, :inline => true %>

<%= setting_text_field :issues_export_limit, :size => 6 %>

diff --git a/app/views/settings/_repositories.html.erb b/app/views/settings/_repositories.html.erb index adac52fc778..f89a27944a3 100644 --- a/app/views/settings/_repositories.html.erb +++ b/app/views/settings/_repositories.html.erb @@ -114,7 +114,7 @@ <%= select_tag("settings[commit_update_keywords][done_ratio][]", options_for_select( [["", ""]] + - (0..10).to_a.collect {|r| ["#{r*10} %", "#{r*10}"] }, + (0..100).step(Setting.issue_done_ratio_interval.to_i).to_a.collect {|r| ["#{r} %", r]}, rule['done_ratio']), :id => nil ) %> diff --git a/config/locales/en.yml b/config/locales/en.yml index c842e4d7b9b..2361dac0820 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -477,6 +477,7 @@ en: setting_default_projects_modules: Default enabled modules for new projects setting_issue_done_ratio: Calculate the issue done ratio with setting_issue_done_ratio_issue_field: Use the issue field + setting_issue_done_ratio_interval: Done ratio options interval setting_issue_done_ratio_issue_status: Use the issue status setting_start_of_week: Start calendars on setting_rest_api_enabled: Enable REST web service diff --git a/config/settings.yml b/config/settings.yml index bd37957560b..346288a4a2a 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -256,6 +256,9 @@ default_project_query: default: '' issue_done_ratio: default: 'issue_field' +issue_done_ratio_interval: + format: int + default: 10 default_projects_public: default: 1 default_projects_modules: diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index 53cfd814657..12ec7a6d5ae 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -8736,4 +8736,19 @@ def test_index_should_ignore_global_default_query_if_it_is_not_public end end end + + def test_get_new_with_issue_field_five_percent_increments + with_settings :issue_done_ratio => 'issue_field', :issue_done_ratio_interval => 5 do + @request.session[:user_id] = 1 + get :new + assert_response :success + + assert_select 'select#issue_done_ratio' do + assert_select 'option', count: 21 + assert_select 'option:nth-of-type(1)', text: '0 %' + assert_select 'option:nth-of-type(2)', text: '5 %' + assert_select 'option:nth-of-type(21)', text: '100 %' + end + end + end end From 7c2098119a8a7e94cbde4725cf9293ff763f1a69 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 29 May 2024 15:11:26 +0000 Subject: [PATCH 043/459] Update locales (#31756). git-svn-id: https://svn.redmine.org/redmine/trunk@22850 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/ar.yml | 1 + config/locales/az.yml | 1 + config/locales/bg.yml | 1 + config/locales/bs.yml | 1 + config/locales/ca.yml | 1 + config/locales/cs.yml | 1 + config/locales/da.yml | 1 + config/locales/de.yml | 1 + config/locales/el.yml | 1 + config/locales/en-GB.yml | 1 + config/locales/es-PA.yml | 1 + config/locales/es.yml | 1 + config/locales/et.yml | 1 + config/locales/eu.yml | 1 + config/locales/fa.yml | 1 + config/locales/fi.yml | 1 + config/locales/fr.yml | 1 + config/locales/gl.yml | 1 + config/locales/he.yml | 1 + config/locales/hr.yml | 1 + config/locales/hu.yml | 1 + config/locales/id.yml | 1 + config/locales/it.yml | 1 + config/locales/ja.yml | 1 + config/locales/ko.yml | 1 + config/locales/lt.yml | 1 + config/locales/lv.yml | 1 + config/locales/mk.yml | 1 + config/locales/mn.yml | 1 + config/locales/nl.yml | 1 + config/locales/no.yml | 1 + config/locales/pl.yml | 1 + config/locales/pt-BR.yml | 1 + config/locales/pt.yml | 1 + config/locales/ro.yml | 1 + config/locales/ru.yml | 1 + config/locales/sk.yml | 1 + config/locales/sl.yml | 1 + config/locales/sq.yml | 1 + config/locales/sr-YU.yml | 1 + config/locales/sr.yml | 1 + config/locales/sv.yml | 1 + config/locales/ta-IN.yml | 1 + config/locales/th.yml | 1 + config/locales/tr.yml | 1 + config/locales/uk.yml | 1 + config/locales/vi.yml | 1 + config/locales/zh-TW.yml | 1 + config/locales/zh.yml | 1 + 49 files changed, 49 insertions(+) diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 92de6e92bbf..23f6f363c7d 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -1490,3 +1490,4 @@ ar: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/az.yml b/config/locales/az.yml index a3b5d661a0f..9d3ab400809 100644 --- a/config/locales/az.yml +++ b/config/locales/az.yml @@ -1582,3 +1582,4 @@ az: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 0108729a611..d9540aca16c 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -1435,3 +1435,4 @@ bg: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/bs.yml b/config/locales/bs.yml index a281d19b81a..c1fec2dfb40 100644 --- a/config/locales/bs.yml +++ b/config/locales/bs.yml @@ -1477,3 +1477,4 @@ bs: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 4739460e550..5c3555488a0 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -1477,3 +1477,4 @@ ca: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 8f14bb3b276..9d67794ec6f 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1472,3 +1472,4 @@ cs: label_issue_attachment_added: Příloha přidána field_estimated_remaining_hours: Odhadovaný zbývající čas field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/da.yml b/config/locales/da.yml index bdf3882a915..12bba6ae861 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -1507,3 +1507,4 @@ da: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/de.yml b/config/locales/de.yml index c348a64bea6..93fda880a55 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1454,3 +1454,4 @@ de: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/el.yml b/config/locales/el.yml index 10d2673dc0a..6dcdec7088c 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -1490,3 +1490,4 @@ el: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index c79496dec2e..f54073ac363 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -1491,3 +1491,4 @@ en-GB: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/es-PA.yml b/config/locales/es-PA.yml index 3e7d287a8c7..91277c8d63b 100644 --- a/config/locales/es-PA.yml +++ b/config/locales/es-PA.yml @@ -1520,3 +1520,4 @@ es-PA: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/es.yml b/config/locales/es.yml index ba2c644a57d..6d83a398a62 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -1556,3 +1556,4 @@ es: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/et.yml b/config/locales/et.yml index f05401452b3..a029a4294e7 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -1495,3 +1495,4 @@ et: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/eu.yml b/config/locales/eu.yml index 37876fad760..0c2d249920a 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -1491,3 +1491,4 @@ eu: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/fa.yml b/config/locales/fa.yml index 83cf8c96495..0997cc4e2b1 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -1424,3 +1424,4 @@ fa: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 3e39ac724e8..0afb7cacde9 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -1511,3 +1511,4 @@ fi: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/fr.yml b/config/locales/fr.yml index e67931c792d..3aced8961c7 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1470,3 +1470,4 @@ fr: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/gl.yml b/config/locales/gl.yml index 77702e0accd..8b835d79a42 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -1495,3 +1495,4 @@ gl: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/he.yml b/config/locales/he.yml index 9c19d937ba4..5fc5444ca78 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -1495,3 +1495,4 @@ he: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/hr.yml b/config/locales/hr.yml index 19495663a0b..4eaefaffaef 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -1487,3 +1487,4 @@ hr: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 9e8970f6cd6..fc2ed6d9363 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -1482,3 +1482,4 @@ label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/id.yml b/config/locales/id.yml index f8074f7a4f9..04c21a40070 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -1492,3 +1492,4 @@ id: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/it.yml b/config/locales/it.yml index 296f98465a7..258178f2ba4 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -1483,3 +1483,4 @@ it: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 7511951d975..3ce888713a6 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1442,3 +1442,4 @@ ja: label_issue_attachment_added: 添付ファイルの追加 field_estimated_remaining_hours: 残工数 field_last_activity_date: 最終活動日 + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/ko.yml b/config/locales/ko.yml index d7b8f14d21d..9f23c5ccdb9 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -1511,3 +1511,4 @@ ko: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/lt.yml b/config/locales/lt.yml index 8d67ab7f49c..43aa3a4da8f 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -1451,3 +1451,4 @@ lt: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 8b659513990..b24be9fdfe4 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -1484,3 +1484,4 @@ lv: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/mk.yml b/config/locales/mk.yml index 8bbbcb3df9c..bf2f8694033 100644 --- a/config/locales/mk.yml +++ b/config/locales/mk.yml @@ -1490,3 +1490,4 @@ mk: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/mn.yml b/config/locales/mn.yml index aee221ca19e..c487a7795a5 100644 --- a/config/locales/mn.yml +++ b/config/locales/mn.yml @@ -1490,3 +1490,4 @@ mn: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 19872c3e94b..7c69dd8d213 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -1465,3 +1465,4 @@ nl: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/no.yml b/config/locales/no.yml index ea08e0e0895..9bd38e6c031 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -1480,3 +1480,4 @@ label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/pl.yml b/config/locales/pl.yml index a8848923cdb..a56a44c7f17 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -1434,3 +1434,4 @@ pl: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 4c58d757898..dbd502d2670 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -1495,3 +1495,4 @@ pt-BR: label_option_auto_lang: auto label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 4f21e01fd6a..2d7283b2e6b 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -1483,3 +1483,4 @@ pt: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/ro.yml b/config/locales/ro.yml index 4bd56f2affc..ea1ce21e99e 100644 --- a/config/locales/ro.yml +++ b/config/locales/ro.yml @@ -1485,3 +1485,4 @@ ro: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 1935bb8e695..c56e13052fe 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -1560,3 +1560,4 @@ ru: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 5c3e4c6a2ae..d9aef73e39c 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -1479,3 +1479,4 @@ sk: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 3eb5d94d9f6..4ae2fb306be 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -1490,3 +1490,4 @@ sl: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/sq.yml b/config/locales/sq.yml index a833b67341d..7ed5087c9b2 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -1452,3 +1452,4 @@ sq: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/sr-YU.yml b/config/locales/sr-YU.yml index c9b85126c18..23798be1133 100644 --- a/config/locales/sr-YU.yml +++ b/config/locales/sr-YU.yml @@ -1492,3 +1492,4 @@ sr-YU: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 1f5e1d24b6b..ff89358c4a2 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -1491,3 +1491,4 @@ sr: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 2f919b8980b..455d199754e 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -1523,3 +1523,4 @@ sv: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/ta-IN.yml b/config/locales/ta-IN.yml index 25e2b958d2e..8602ee50a58 100644 --- a/config/locales/ta-IN.yml +++ b/config/locales/ta-IN.yml @@ -1446,3 +1446,4 @@ ta-IN: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/th.yml b/config/locales/th.yml index 39309a59315..6128b6105e0 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -1486,3 +1486,4 @@ th: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 57477e4ad3b..c18ae403ccc 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -1489,3 +1489,4 @@ tr: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 2e0b781c295..ead37b67f58 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -1478,3 +1478,4 @@ uk: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 366b8d79d89..43027ba21f6 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -1495,3 +1495,4 @@ vi: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 2374e0c4e56..8436e726efe 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -1507,3 +1507,4 @@ label_issue_attachment_added: 附加檔案已新增 field_estimated_remaining_hours: 預估剩餘工時 field_last_activity_date: 最近一次活動 + setting_issue_done_ratio_interval: Done ratio options interval diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 4739d33a648..86d79d79690 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -1426,3 +1426,4 @@ zh: label_issue_attachment_added: Attachment added field_estimated_remaining_hours: Estimated remaining time field_last_activity_date: Last activity + setting_issue_done_ratio_interval: Done ratio options interval From 4033b697984839024827f163879a93cfe7d0df13 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 29 May 2024 15:22:55 +0000 Subject: [PATCH 044/459] Japanese translation update (#40749). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22851 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/ja.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 3ce888713a6..4bdb3f71639 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1442,4 +1442,4 @@ ja: label_issue_attachment_added: 添付ファイルの追加 field_estimated_remaining_hours: 残工数 field_last_activity_date: 最終活動日 - setting_issue_done_ratio_interval: Done ratio options interval + setting_issue_done_ratio_interval: 進捗率の選択肢の間隔 From 508ee8a8586442b900f47a554d33241039fdce1d Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Sun, 2 Jun 2024 01:55:18 +0000 Subject: [PATCH 045/459] Traditional Chinese translation update (#40762). Patch by ChunChang (Nagaharu) Lo (@shortie). git-svn-id: https://svn.redmine.org/redmine/trunk@22852 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/zh-TW.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 8436e726efe..7e508e48baa 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -1507,4 +1507,4 @@ label_issue_attachment_added: 附加檔案已新增 field_estimated_remaining_hours: 預估剩餘工時 field_last_activity_date: 最近一次活動 - setting_issue_done_ratio_interval: Done ratio options interval + setting_issue_done_ratio_interval: 完成百分比選項的間隔值 From 70903787566df1f1e3ded8f82abd48b29a01f6ca Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Sun, 2 Jun 2024 02:04:05 +0000 Subject: [PATCH 046/459] Bulgarian translation update (#40771). Patch by Ivan Cenov (@jwalker). git-svn-id: https://svn.redmine.org/redmine/trunk@22853 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/locales/bg.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/locales/bg.yml b/config/locales/bg.yml index d9540aca16c..a218e214c34 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -420,7 +420,9 @@ bg: field_default_issue_query: Заявка по подразбиране field_default_project_query: Заявка по подразбиране за проекта field_default_time_entry_activity: Дейност по подразбиране за изразходвано време + field_estimated_remaining_hours: Изчислено оставащо време field_any_searchable: Всички обекти с текст (заглавие, описание, коментари на задачи, потребителски полета) + field_last_activity_date: Последна активност setting_app_title: Заглавие setting_welcome_text: Допълнителен текст @@ -478,6 +480,7 @@ bg: setting_default_projects_modules: Активирани модули по подразбиране за нов проект setting_issue_done_ratio: Изчисление на процента на готови задачи с setting_issue_done_ratio_issue_field: Използване на поле '% Прогрес' + setting_issue_done_ratio_interval: Done ratio options interval setting_issue_done_ratio_issue_status: Използване на състоянието на задачите setting_start_of_week: Първи ден на седмицата setting_rest_api_enabled: Разрешаване на REST web сървис @@ -632,6 +635,7 @@ bg: label_issue_assigned_to_updated: Задачата е с назначен нов изпълнител label_issue_priority_updated: Обновен приоритет label_issue_fixed_version_updated: Променена версия + label_issue_attachment_added: Добавен файл label_document: Документ label_document_new: Нов документ label_document_plural: Документи @@ -882,6 +886,7 @@ bg: label_diff_inline: хоризонтално label_diff_side_by_side: вертикално label_options: Опции + label_option_auto_lang: автоматично label_copy_workflow_from: Копирай работния процес от label_permissions_report: Справка за права label_watched_issues: Наблюдавани задачи @@ -1431,8 +1436,3 @@ bg: За да потвърдите, въведете името (%{login}) по-долу. text_project_destroy_enter_identifier: За да потвърдите действието, въведете идентификатора на проекта (%{identifier}) по-долу. field_name_or_email_or_login: Име, e-mail или login име - label_option_auto_lang: auto - label_issue_attachment_added: Attachment added - field_estimated_remaining_hours: Estimated remaining time - field_last_activity_date: Last activity - setting_issue_done_ratio_interval: Done ratio options interval From c19176a5c48e33e6bcfe280736092154deb58181 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Tue, 4 Jun 2024 09:37:34 +0000 Subject: [PATCH 047/459] Reduce an extra SQL query in IssuesController#retrieve_default_query (#40775). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22854 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/issues_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 76e7ed921cf..8528a2fcace 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -502,8 +502,9 @@ def retrieve_default_query(use_session) return end if !params[:set_filter] && use_session && session[:issue_query] + # Don't apply the default query if a valid query id is set in the session query_id, project_id = session[:issue_query].values_at(:id, :project_id) - return if IssueQuery.where(id: query_id).exists? && project_id == @project&.id + return if query_id && project_id == @project&.id && IssueQuery.exists?(id: query_id) end if default_query = IssueQuery.default(project: @project) params[:query_id] = default_query.id From 38a8adb2a20c9c6ae57b0633037290c64a34b624 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Tue, 4 Jun 2024 20:04:45 +0000 Subject: [PATCH 048/459] Adds description field to custom queries (#9309). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22855 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/queries_controller.rb | 1 + app/helpers/queries_helper.rb | 3 +- app/models/query.rb | 1 + app/views/admin/projects.html.erb | 1 + app/views/calendars/show.html.erb | 1 + app/views/gantts/show.html.erb | 1 + app/views/issues/index.html.erb | 1 + app/views/projects/index.html.erb | 1 + app/views/queries/_form.html.erb | 2 + app/views/timelog/index.html.erb | 1 + app/views/users/index.html.erb | 1 + .../20240213101801_add_queries_description.rb | 9 ++++ test/fixtures/queries.yml | 12 +++++ test/functional/calendars_controller_test.rb | 7 +-- test/functional/gantts_controller_test.rb | 13 ++++++ test/functional/issues_controller_test.rb | 3 +- test/functional/projects_controller_test.rb | 9 ++++ test/functional/queries_controller_test.rb | 44 +++++++++++++++++++ test/functional/timelog_controller_test.rb | 4 +- test/functional/users_controller_test.rb | 9 ++++ 20 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20240213101801_add_queries_description.rb diff --git a/app/controllers/queries_controller.rb b/app/controllers/queries_controller.rb index db5d785f97b..53ce029b917 100644 --- a/app/controllers/queries_controller.rb +++ b/app/controllers/queries_controller.rb @@ -133,6 +133,7 @@ def update_query_from_params @query.column_names = nil if params[:default_columns] @query.sort_criteria = (params[:query] && params[:query][:sort_criteria]) || @query.sort_criteria @query.name = params[:query] && params[:query][:name] + @query.description = params[:query] && params[:query][:description] if User.current.allowed_to?(:manage_public_queries, @query.project) || User.current.admin? @query.visibility = (params[:query] && params[:query][:visibility]) || Query::VISIBILITY_PRIVATE @query.role_ids = params[:query] && params[:query][:role_ids] diff --git a/app/helpers/queries_helper.rb b/app/helpers/queries_helper.rb index 160473ae8ae..453149436a6 100644 --- a/app/helpers/queries_helper.rb +++ b/app/helpers/queries_helper.rb @@ -506,7 +506,8 @@ def query_links(title, queries) content_tag('li', link_to(query.name, url_params.merge(:query_id => query), - :class => css) + + :class => css, + :title => query.description) + clear_link.html_safe) end.join("\n").html_safe, :class => 'queries' diff --git a/app/models/query.rb b/app/models/query.rb index 90970c96e6d..931abc95878 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -270,6 +270,7 @@ class QueryError < StandardError validates_presence_of :name validates_length_of :name, :maximum => 255 + validates_length_of :description, :maximum => 255 validates :visibility, :inclusion => {:in => [VISIBILITY_PUBLIC, VISIBILITY_ROLES, VISIBILITY_PRIVATE]} validate :validate_query_filters validate do |query| diff --git a/app/views/admin/projects.html.erb b/app/views/admin/projects.html.erb index e6805453ae7..c0e2a713e8b 100644 --- a/app/views/admin/projects.html.erb +++ b/app/views/admin/projects.html.erb @@ -3,6 +3,7 @@

<%= @query.new_record? ? l(:label_project_plural) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description, class: 'subtitle') : '' %> <%= form_tag(admin_projects_path(@project, nil), :method => :get, :id => 'query_form') do %> <%= hidden_field_tag 'admin_projects', '1' %> diff --git a/app/views/calendars/show.html.erb b/app/views/calendars/show.html.erb index d3d00a427eb..dfef117dee3 100644 --- a/app/views/calendars/show.html.erb +++ b/app/views/calendars/show.html.erb @@ -1,4 +1,5 @@

<%= @query.new_record? ? l(:label_calendar) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description, class: 'subtitle') : '' %> <%= form_tag({:controller => 'calendars', :action => 'show', :project_id => @project}, :method => :get, :id => 'query_form') do %> diff --git a/app/views/gantts/show.html.erb b/app/views/gantts/show.html.erb index 43e430311dd..ceca3d1a714 100644 --- a/app/views/gantts/show.html.erb +++ b/app/views/gantts/show.html.erb @@ -3,6 +3,7 @@

<%= @query.new_record? ? l(:label_gantt) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description, class: 'subtitle') : '' %> <%= form_tag({:controller => 'gantts', :action => 'show', :project_id => @project, :month => params[:month], diff --git a/app/views/issues/index.html.erb b/app/views/issues/index.html.erb index 997a64e5554..1ab5198a1d2 100644 --- a/app/views/issues/index.html.erb +++ b/app/views/issues/index.html.erb @@ -19,6 +19,7 @@

<%= @query.new_record? ? l(:label_issue_plural) : @query.name %>

<% html_title(@query.new_record? ? l(:label_issue_plural) : @query.name) %> +<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description, class: 'subtitle') : '' %> <%= form_tag(_project_issues_path(@project), :method => :get, :id => 'query_form') do %> <%= render :partial => 'queries/query_form' %> diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb index 3bd665640dd..d18cf6e4713 100644 --- a/app/views/projects/index.html.erb +++ b/app/views/projects/index.html.erb @@ -5,6 +5,7 @@

<%= @query.new_record? ? l(:label_project_plural) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description, class: 'subtitle') : '' %> <%= form_tag(projects_path(@project, nil), :method => :get, :id => 'query_form') do %> <%= render :partial => 'queries/query_form' %> diff --git a/app/views/queries/_form.html.erb b/app/views/queries/_form.html.erb index 5f4fa34909e..27391e8ef9d 100644 --- a/app/views/queries/_form.html.erb +++ b/app/views/queries/_form.html.erb @@ -8,6 +8,8 @@

<%= text_field 'query', 'name', :size => 80 %>

+

+<%= text_field 'query', 'description', :size => 80 %>

<% if User.current.admin? || User.current.allowed_to?(:manage_public_queries, @query.project) %> diff --git a/app/views/timelog/index.html.erb b/app/views/timelog/index.html.erb index a045e47439f..ec7580b9a2d 100644 --- a/app/views/timelog/index.html.erb +++ b/app/views/timelog/index.html.erb @@ -14,6 +14,7 @@

<%= @query.new_record? ? l(:label_spent_time) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description, class: 'subtitle') : '' %> <%= form_tag(_time_entries_path(@project, nil), :method => :get, :id => 'query_form') do %> <%= render :partial => 'date_range' %> diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index d609bfd7832..9071dba1943 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -8,6 +8,7 @@

<%= @query.new_record? ? l(:label_user_plural) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description, class: 'subtitle') : '' %> <%= form_tag(users_path, method: :get, id: 'query_form') do %> <%= render partial: 'queries/query_form' %> diff --git a/db/migrate/20240213101801_add_queries_description.rb b/db/migrate/20240213101801_add_queries_description.rb new file mode 100644 index 00000000000..5755731c953 --- /dev/null +++ b/db/migrate/20240213101801_add_queries_description.rb @@ -0,0 +1,9 @@ +class AddQueriesDescription < ActiveRecord::Migration[6.1] + def up + add_column :queries, :description, :string, :after => :name + end + + def down + remove_column :queries, :description + end +end diff --git a/test/fixtures/queries.yml b/test/fixtures/queries.yml index 6b3bb0193dd..cc0ea220f97 100644 --- a/test/fixtures/queries.yml +++ b/test/fixtures/queries.yml @@ -5,6 +5,7 @@ queries_001: project_id: 1 visibility: 2 name: Multiple custom fields query + description: Description for Multiple custom fields query filters: | --- cf_1: @@ -28,6 +29,7 @@ queries_002: project_id: 1 visibility: 0 name: Private query for cookbook + description: Description for Private query for cookbook filters: | --- tracker_id: @@ -47,6 +49,7 @@ queries_003: project_id: visibility: 0 name: Private query for all projects + description: Description for Private query for all projects filters: | --- tracker_id: @@ -62,6 +65,7 @@ queries_004: project_id: visibility: 2 name: Public query for all projects + description: Description for Public query for all projects filters: | --- tracker_id: @@ -77,6 +81,7 @@ queries_005: project_id: visibility: 2 name: Open issues by priority and tracker + description: Description for Oepn issues by priority and tracker filters: | --- status_id: @@ -98,6 +103,7 @@ queries_006: project_id: visibility: 2 name: Open issues grouped by tracker + description: Description for Open issues grouped by tracker filters: | --- status_id: @@ -118,6 +124,7 @@ queries_007: project_id: 2 visibility: 2 name: Public query for project 2 + description: Description for Public query for project 2 filters: | --- tracker_id: @@ -133,6 +140,7 @@ queries_008: project_id: 2 visibility: 0 name: Private query for project 2 + description: Description for Private query for project 2 filters: | --- tracker_id: @@ -148,6 +156,7 @@ queries_009: project_id: visibility: 2 name: Open issues grouped by list custom field + description: Description for Open issues grouped by list custom field filters: | --- status_id: @@ -168,6 +177,7 @@ queries_010: project_id: 1 visibility: 2 name: My spent time + description: Description for My spent time filters: | --- user_id: @@ -187,6 +197,7 @@ queries_011: type: ProjectQuery visibility: 2 name: Projects as list + description: Description for Projects as list filters: | --- id: @@ -205,6 +216,7 @@ queries_012: type: ProjectQuery visibility: 1 name: My bookmarks + description: Description for My bookmarks filters: | --- id: diff --git a/test/functional/calendars_controller_test.rb b/test/functional/calendars_controller_test.rb index f77872ea28d..134d41cbe30 100644 --- a/test/functional/calendars_controller_test.rb +++ b/test/functional/calendars_controller_test.rb @@ -155,15 +155,16 @@ def test_show_version end def test_show_should_run_custom_queries - @query = IssueQuery.create!(:name => 'Calendar Query', :visibility => IssueQuery::VISIBILITY_PUBLIC) + query = IssueQuery.create!(:name => 'Calendar Query', :description => 'Description for Calendar Query', :visibility => IssueQuery::VISIBILITY_PUBLIC) get( :show, :params => { - :query_id => @query.id + :query_id => query.id } ) assert_response :success - assert_select 'h2', :text => 'Calendar Query' + assert_select 'h2', :text => query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name end def test_cross_project_calendar diff --git a/test/functional/gantts_controller_test.rb b/test/functional/gantts_controller_test.rb index 821294bba69..48dfc8ae795 100644 --- a/test/functional/gantts_controller_test.rb +++ b/test/functional/gantts_controller_test.rb @@ -118,6 +118,19 @@ def test_gantt_should_work_without_issue_and_version_due_dates assert_response :success end + def test_show_should_run_custom_query + query = IssueQuery.create!(:name => 'Gantt Query', :description => 'Description for Gantt Query', :visibility => IssueQuery::VISIBILITY_PUBLIC) + get( + :show, + :params => { + :query_id => query.id + } + ) + assert_response :success + assert_select 'h2', :text => query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name + end + def test_gantt_should_work_cross_project get :show assert_response :success diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index 12ec7a6d5ae..ca09ee8f11b 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -359,7 +359,8 @@ def test_index_with_query assert_select 'a.query.selected', 1 # assert link properties assert_select( - 'a.query.selected[href=?]', + 'a.query.selected[title=?][href=?]', + 'Description for Oepn issues by priority and tracker', '/projects/ecookbook/issues?query_id=5', :text => "Open issues by priority and tracker" ) diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index a21b50b077b..80773e0d267 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -267,6 +267,14 @@ def test_index_with_last_activity_date_column assert_select 'tr#project-4 td.last_activity_date', :text => '' end + def test_index_with_query + query = ProjectQuery.find(11) + get :index, :params => { :query_id => query.id } + assert_response :success + assert_select 'h2', :text => query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name + end + def test_index_should_retrieve_default_query query = ProjectQuery.find(11) ProjectQuery.stubs(:default).returns query @@ -275,6 +283,7 @@ def test_index_should_retrieve_default_query @request.session[:user_id] = user_id get :index assert_select 'h2', text: query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name end end diff --git a/test/functional/queries_controller_test.rb b/test/functional/queries_controller_test.rb index 77560e9137f..7c8b5cd9ae1 100644 --- a/test/functional/queries_controller_test.rb +++ b/test/functional/queries_controller_test.rb @@ -328,6 +328,25 @@ def test_create_with_sort assert_equal [['due_date', 'desc'], ['tracker', 'asc']], query.sort_criteria end + def test_create_with_description + @request.session[:user_id] = 2 + assert_difference '::Query.count', 1 do + post( + :create, + :params => { + :project_id => 'ecookbook', + :query => { + :name => 'test_new_with_description', :description => 'Description for test_new_with_description' + } + } + ) + end + q = Query.find_by_name("test_new_with_description") + assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q + + assert_equal 'Description for test_new_with_description', q.description + end + def test_create_with_failure @request.session[:user_id] = 2 assert_no_difference '::Query.count' do @@ -659,6 +678,14 @@ def test_edit_sort_criteria end end + def test_edit_description + @request.session[:user_id] = 1 + get(:edit, :params => {:id => 5}) + assert_response :success + + assert_select 'input[name="query[description]"][value=?]', 'Description for Oepn issues by priority and tracker' + end + def test_edit_invalid_query @request.session[:user_id] = 2 get(:edit, :params => {:id => 99}) @@ -744,6 +771,23 @@ def test_update_admin_projects_query assert Query.find_by_name('test_project_query_updated') end + def test_update_description + @request.session[:user_id] = 1 + q = Query.find(5) + put( + :update, + :params => { + :id => q.id, + :query => { + :name => q.name, + :description => 'query description updated' + } + } + ) + assert_redirected_to :controller => 'issues', :action => 'index', :query_id => q.id + assert_equal 'query description updated', Query.find(5).description + end + def test_update_with_failure @request.session[:user_id] = 1 put( diff --git a/test/functional/timelog_controller_test.rb b/test/functional/timelog_controller_test.rb index 464bf932772..5a63a8c61cb 100644 --- a/test/functional/timelog_controller_test.rb +++ b/test/functional/timelog_controller_test.rb @@ -1682,14 +1682,14 @@ def test_index_with_invalid_date_filter_should_not_validate end def test_index_with_query - query = TimeEntryQuery.new(:project_id => 1, :name => 'Time Entry Query', :visibility => 2) + query = TimeEntryQuery.new(:project_id => 1, :name => 'Time Entry Query', :description => 'Description for Time Entry Query', :visibility => 2) query.save! @request.session[:user_id] = 2 get :index, :params => {:project_id => 'ecookbook', :query_id => query.id} assert_response :success assert_select 'h2', :text => query.name - assert_select '#sidebar a.selected', :text => query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name end def test_index_atom_feed diff --git a/test/functional/users_controller_test.rb b/test/functional/users_controller_test.rb index 4302f913a9b..5d6e6b754fb 100644 --- a/test/functional/users_controller_test.rb +++ b/test/functional/users_controller_test.rb @@ -189,6 +189,15 @@ def test_index_with_auth_source_column assert_select 'tr#user-1', 1 end + def test_index_with_query + query = UserQuery.create!(:name => 'My User Query', :description => 'Description for My User Query', :visibility => UserQuery::VISIBILITY_PUBLIC) + get :index, :params => { :query_id => query.id } + assert_response :success + + assert_select 'h2', :text => query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name + end + def test_index_csv with_settings :default_language => 'en' do user = User.logged.status(1).first From 7710d005f268b4defc6351396f1dc1f0e28fe8ac Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Tue, 4 Jun 2024 20:05:26 +0000 Subject: [PATCH 049/459] Set migration version to 7.1 (#9309). git-svn-id: https://svn.redmine.org/redmine/trunk@22856 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- db/migrate/20240213101801_add_queries_description.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20240213101801_add_queries_description.rb b/db/migrate/20240213101801_add_queries_description.rb index 5755731c953..b2d7d57e24c 100644 --- a/db/migrate/20240213101801_add_queries_description.rb +++ b/db/migrate/20240213101801_add_queries_description.rb @@ -1,4 +1,4 @@ -class AddQueriesDescription < ActiveRecord::Migration[6.1] +class AddQueriesDescription < ActiveRecord::Migration[7.1] def up add_column :queries, :description, :string, :after => :name end From d9ca32b9d14bc5b2b260fee343a012b43fdf6e80 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Tue, 4 Jun 2024 20:16:08 +0000 Subject: [PATCH 050/459] Move logic for estimated remaining hours from @QueryColumn@ to @Issue@ (#37862). git-svn-id: https://svn.redmine.org/redmine/trunk@22857 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/issue.rb | 5 +++++ app/models/issue_query.rb | 23 +++++------------------ 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/app/models/issue.rb b/app/models/issue.rb index ad4728444a3..fdca171c991 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -1165,6 +1165,11 @@ def total_estimated_hours end end + # Returns the number of estimated remaining hours on this issue + def estimated_remaining_hours + (estimated_hours || 0) * (100 - (done_ratio || 0)) / 100 + end + def relations @relations ||= IssueRelation::Relations.new( self, diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb index c4b08158fd9..9c78fd734ad 100644 --- a/app/models/issue_query.rb +++ b/app/models/issue_query.rb @@ -18,25 +18,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class IssueQuery < Query - class EstimatedRemainingHoursColumn < QueryColumn - COLUMN_SQL = Arel.sql("COALESCE(#{Issue.table_name}.estimated_hours, 0) * (100 - COALESCE(#{Issue.table_name}.done_ratio, 0)) / 100") - - def initialize - super(:estimated_remaining_hours, totalable: true, sortable: COLUMN_SQL) - end - - def value(object) - (object.estimated_hours || 0) * (100 - (object.done_ratio || 0)) / 100 - end - - def value_object(object) - value(object) - end - end - self.queried_class = Issue self.view_permission = :view_issues + ESTIMATED_REMAINING_HOURS_SQL = Arel.sql("COALESCE(#{Issue.table_name}.estimated_hours, 0) * (100 - COALESCE(#{Issue.table_name}.done_ratio, 0)) / 100") self.available_columns = [ QueryColumn.new(:id, :sortable => "#{Issue.table_name}.id", :default_order => 'desc', :caption => '#', :frozen => true), @@ -66,7 +51,9 @@ def value_object(object) QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date", :groupable => true), QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours", :totalable => true), - EstimatedRemainingHoursColumn.new, + QueryColumn.new(:estimated_remaining_hours, + :sortable => ESTIMATED_REMAINING_HOURS_SQL, + :totalable => true), QueryColumn.new( :total_estimated_hours, :sortable => @@ -390,7 +377,7 @@ def total_for_estimated_hours(scope) end def total_for_estimated_remaining_hours(scope) - map_total(scope.sum(EstimatedRemainingHoursColumn::COLUMN_SQL)) {|t| t.to_f.round(2)} + map_total(scope.sum(ESTIMATED_REMAINING_HOURS_SQL)) {|t| t.to_f.round(2)} end # Returns sum of all the issue's time entries hours From 82c88b370058a37a972fdd27f3b523fae79cb252 Mon Sep 17 00:00:00 2001 From: Marius Balteanu Date: Tue, 4 Jun 2024 20:17:01 +0000 Subject: [PATCH 051/459] Adds estimated remaining time to version page (#37862, #1671). git-svn-id: https://svn.redmine.org/redmine/trunk@22858 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/version.rb | 12 ++++++++++++ app/views/versions/show.html.erb | 7 +++++++ test/unit/version_test.rb | 20 ++++++++++++-------- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/app/models/version.rb b/app/models/version.rb index 937ec9221c7..c0d4d0deee3 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -24,6 +24,12 @@ def estimated_hours @estimated_hours ||= sum(:estimated_hours).to_f end + # Returns the total estimated remaining time for this version + # (sum of leaves remaining_estimated_hours) + def estimated_remaining_hours + @estimated_remaining_hours ||= sum(IssueQuery::ESTIMATED_REMAINING_HOURS_SQL).to_f + end + # Returns the total amount of open issues for this version. def open_count load_counts @@ -241,6 +247,12 @@ def estimated_hours fixed_issues.estimated_hours end + # Returns the total estimated remaining time for this version + # (sum of leaves estimated_remaining_hours) + def estimated_remaining_hours + @remaining_hours ||= fixed_issues.estimated_remaining_hours + end + # Returns the total reported time for this version def spent_hours @spent_hours ||= TimeEntry.joins(:issue).where("#{Issue.table_name}.fixed_version_id = ?", id).sum(:hours).to_f diff --git a/app/views/versions/show.html.erb b/app/views/versions/show.html.erb index e1757107586..88eb4b84126 100644 --- a/app/views/versions/show.html.erb +++ b/app/views/versions/show.html.erb @@ -22,6 +22,13 @@ <%= link_to html_hours(l_hours(@version.visible_fixed_issues.estimated_hours)), project_issues_path(@version.project, :set_filter => 1, :status_id => '*', :fixed_version_id => @version.id, :c => [:tracker, :status, :subject, :estimated_hours], :t => [:estimated_hours]) %> + + <%= l(:field_estimated_remaining_hours) %> + + <%= link_to html_hours(l_hours(@version.visible_fixed_issues.estimated_remaining_hours)), + project_issues_path(@version.project, :set_filter => 1, :status_id => '*', :fixed_version_id => @version.id, :c => [:tracker, :status, :subject, :estimated_remaining_hours], :t => [:estimated_remaining_hours]) %> + + <% if User.current.allowed_to_view_all_time_entries?(@project) %> <%= l(:label_spent_time) %> diff --git a/test/unit/version_test.rb b/test/unit/version_test.rb index d7274ca9a1a..409f1494cae 100644 --- a/test/unit/version_test.rb +++ b/test/unit/version_test.rb @@ -225,30 +225,34 @@ def test_completed_should_be_true_when_closed assert_equal false, version.behind_schedule? end - test "#estimated_hours should return 0 with no assigned issues" do + test "#estimated_hours and estimated_remaining_hours should return 0 with no assigned issues" do version = Version.generate! assert_equal 0, version.estimated_hours + assert_equal 0, version.estimated_remaining_hours end - test "#estimated_hours should return 0 with no estimated hours" do + test "#estimated_hours and estimated_remaining_hours should return 0 with no estimated hours" do version = Version.create!(:project_id => 1, :name => 'test') add_issue(version) assert_equal 0, version.estimated_hours + assert_equal 0, version.estimated_remaining_hours end - test "#estimated_hours should return return the sum of estimated hours" do + test "#estimated_hours and estimated_remaining_hours should return the sum of estimated hours and estimated remaining hours" do version = Version.create!(:project_id => 1, :name => 'test') - add_issue(version, :estimated_hours => 2.5) - add_issue(version, :estimated_hours => 5) + add_issue(version, :estimated_hours => 2.5, :done_ratio => 90) + add_issue(version, :estimated_hours => 5, :done_ratio => 50) assert_equal 7.5, version.estimated_hours + assert_equal 2.75, version.estimated_remaining_hours end - test "#estimated_hours should return the sum of leaves estimated hours" do + test "#estimated_hours and remaining_hours should return the sum of leaves estimated hours and estimated remaining hours" do version = Version.create!(:project_id => 1, :name => 'test') parent = add_issue(version) - add_issue(version, :estimated_hours => 2.5, :parent_issue_id => parent.id) - add_issue(version, :estimated_hours => 5, :parent_issue_id => parent.id) + add_issue(version, :estimated_hours => 2.5, :done_ratio => 90, :parent_issue_id => parent.id) + add_issue(version, :estimated_hours => 5, :done_ratio => 50, :parent_issue_id => parent.id) assert_equal 7.5, version.estimated_hours + assert_equal 2.75, version.estimated_remaining_hours end test "should update all issue's fixed_version associations in case the hierarchy changed XXX" do From 5159d31a8bd83da1f7c587634cacdf8faa44555d Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 5 Jun 2024 07:55:45 +0000 Subject: [PATCH 052/459] Remove unsupported :after option from add_column in AddQueriesDescription migration (#9309). git-svn-id: https://svn.redmine.org/redmine/trunk@22859 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- db/migrate/20240213101801_add_queries_description.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20240213101801_add_queries_description.rb b/db/migrate/20240213101801_add_queries_description.rb index b2d7d57e24c..522dbb2dc24 100644 --- a/db/migrate/20240213101801_add_queries_description.rb +++ b/db/migrate/20240213101801_add_queries_description.rb @@ -1,6 +1,6 @@ class AddQueriesDescription < ActiveRecord::Migration[7.1] def up - add_column :queries, :description, :string, :after => :name + add_column :queries, :description, :string end def down From f9eb77227a1eb5df9f265b18db0b7ab65cac4e77 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 5 Jun 2024 08:21:59 +0000 Subject: [PATCH 053/459] Fix RuboCop offense Naming/MemoizedInstanceVariableName (#37862, #1671). git-svn-id: https://svn.redmine.org/redmine/trunk@22860 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/version.rb b/app/models/version.rb index c0d4d0deee3..b1327f068d5 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -250,7 +250,7 @@ def estimated_hours # Returns the total estimated remaining time for this version # (sum of leaves estimated_remaining_hours) def estimated_remaining_hours - @remaining_hours ||= fixed_issues.estimated_remaining_hours + @estimated_remaining_hours ||= fixed_issues.estimated_remaining_hours end # Returns the total reported time for this version From 8e7dce288ba59b8755fec7c7ff519f98d4005f4d Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Thu, 6 Jun 2024 00:53:06 +0000 Subject: [PATCH 054/459] Disable RuboCop Style/NumericPredicate (#39887). git-svn-id: https://svn.redmine.org/redmine/trunk@22861 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .rubocop.yml | 3 +++ .rubocop_todo.yml | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 52c4db3f5f4..ff1a57bb217 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -245,6 +245,9 @@ Style/InverseMethods: Style/NegatedIfElseCondition: Enabled: false +Style/NumericPredicate: + Enabled: false + Style/RaiseArgs: Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 51845adb240..5b4a0213773 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1233,12 +1233,6 @@ Style/NumericLiteralPrefix: Style/NumericLiterals: MinDigits: 9 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. -# SupportedStyles: predicate, comparison -Style/NumericPredicate: - Enabled: false - # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: From c1335f51266cd69ece60a9d12396f3668466fca9 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Thu, 6 Jun 2024 01:20:23 +0000 Subject: [PATCH 055/459] Suppress RuboCop false positive for Security/Open (#39887). git-svn-id: https://svn.redmine.org/redmine/trunk@22862 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .rubocop_todo.yml | 4 ---- app/models/version.rb | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 5b4a0213773..2f7eb1c7870 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -802,10 +802,6 @@ Security/IoMethods: - 'test/functional/mail_handler_controller_test.rb' - 'test/unit/mail_handler_test.rb' -Security/Open: - Exclude: - - 'app/models/version.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). Security/YAMLLoad: Exclude: diff --git a/app/models/version.rb b/app/models/version.rb index b1327f068d5..eed2e22d76b 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -106,7 +106,7 @@ def issues_progress(open) @issues_progress[open] ||= begin progress = 0 if count > 0 - done = open(open).sum do |c| + done = self.open(open).sum do |c| estimated = c.total_estimated_hours.to_f estimated = estimated_average unless estimated > 0.0 ratio = c.closed? ? 100 : (c.done_ratio || 0) From d909b82d32fd3deb3b2a01e253da7aa264ffc89c Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Fri, 7 Jun 2024 04:47:53 +0000 Subject: [PATCH 056/459] Replace BlankSlate with BasicObject for Builder 3.0.0 compatibility (#40802). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Pavel Rosický (@ahorek). git-svn-id: https://svn.redmine.org/redmine/trunk@22863 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/views/builders/json.rb | 2 +- lib/redmine/views/builders/structure.rb | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/redmine/views/builders/json.rb b/lib/redmine/views/builders/json.rb index 47ce0cc9b7d..011c16e5813 100644 --- a/lib/redmine/views/builders/json.rb +++ b/lib/redmine/views/builders/json.rb @@ -28,7 +28,7 @@ class Json < Structure def initialize(request, response) super callback = request.params[:callback] || request.params[:jsonp] - if callback && Setting.jsonp_enabled? + if callback && ::Setting.jsonp_enabled? self.jsonp = callback.to_s.gsub(/[^a-zA-Z0-9_.]/, '') end end diff --git a/lib/redmine/views/builders/structure.rb b/lib/redmine/views/builders/structure.rb index f4524143f9a..ab1e3e4114c 100644 --- a/lib/redmine/views/builders/structure.rb +++ b/lib/redmine/views/builders/structure.rb @@ -17,12 +17,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -require 'blankslate' - module Redmine module Views module Builders - class Structure < BlankSlate + class Structure < BasicObject def initialize(request, response) @struct = [{}] @request = request @@ -38,7 +36,7 @@ def array(tag, options={}, &block) end def encode_value(value) - if value.is_a?(Time) + if value.is_a?(::Time) # Rails uses a global setting to format JSON times # Don't rely on it for the API as it could have been changed value.xmlschema(0) @@ -49,15 +47,15 @@ def encode_value(value) def method_missing(sym, *args, &block) if args.count > 0 - if args.first.is_a?(Hash) - if @struct.last.is_a?(Array) + if args.first.is_a?(::Hash) + if @struct.last.is_a?(::Array) @struct.last << args.first unless block else @struct.last[sym] = args.first end else value = encode_value(args.first) - if @struct.last.is_a?(Array) + if @struct.last.is_a?(::Array) if args.size == 1 && !block @struct.last << value else @@ -69,13 +67,13 @@ def method_missing(sym, *args, &block) end end if block - @struct << (args.first.is_a?(Hash) ? args.first : {}) + @struct << (args.first.is_a?(::Hash) ? args.first : {}) yield(self) ret = @struct.pop - if @struct.last.is_a?(Array) + if @struct.last.is_a?(::Array) @struct.last << ret else - if @struct.last.has_key?(sym) && @struct.last[sym].is_a?(Hash) + if @struct.last.has_key?(sym) && @struct.last[sym].is_a?(::Hash) @struct.last[sym].merge! ret else @struct.last[sym] = ret From e7cae22dfbeef8d588ab2740db5f870cf3202c31 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Tue, 11 Jun 2024 08:37:15 +0000 Subject: [PATCH 057/459] `chmod +x bin/changelog.rb` to make it executable. git-svn-id: https://svn.redmine.org/redmine/trunk@22868 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- bin/changelog.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bin/changelog.rb diff --git a/bin/changelog.rb b/bin/changelog.rb old mode 100644 new mode 100755 From cda357eed15bf98d1684b8425d2c8aff729c5c0c Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 12 Jun 2024 00:27:41 +0000 Subject: [PATCH 058/459] Updates for 5.1.3 release. git-svn-id: https://svn.redmine.org/redmine/trunk@22869 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- doc/CHANGELOG | 33 +++++++++++++++++++++++++++++++++ lib/redmine/version.rb | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/doc/CHANGELOG b/doc/CHANGELOG index b6747156a9c..04ee61b906b 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -4,6 +4,39 @@ Redmine - project management software Copyright (C) 2006- Jean-Philippe Lang https://www.redmine.org/ +== 2024-06-12 v5.1.3 + +=== [Code cleanup/refactoring] + +* Defect #40389: Missing fixture: add :groups_users fixture to Redmine::ApiTest::UsersTest + +=== [Gems support] + +* Defect #40603: Mocha 2.2.0 causes test failure: "unexpected invocation" +* Patch #40802: Support builder 3.3.0 + +=== [Issues] + +* Defect #40410: Watcher groups on new issue form get dereferenced on validation error +* Defect #40412: Issue list filter "Watched by: me" only shows issues watched via group for projects with the view_issue_watchers permission +* Feature #40556: Focus on the textarea after clicking the Edit Journal button + +=== [Issues workflow] + +* Patch #40693: Ignore status in roleld_up_status if workflow only defines identity transition + +=== [Performance] + +* Defect #40610: Slow display of projects list when including project description column + +=== [Rails support] + +* Patch #40818: Update Rails to 6.1.7.8 + +=== [Translations] + +* Patch #40682: Czech translation update for 5.1-stable + == 2024-03-04 v5.1.2 === [Activity view] diff --git a/lib/redmine/version.rb b/lib/redmine/version.rb index eaad9c6aeb8..7ce0933dd54 100644 --- a/lib/redmine/version.rb +++ b/lib/redmine/version.rb @@ -24,7 +24,7 @@ module Redmine module VERSION MAJOR = 5 MINOR = 1 - TINY = 2 + TINY = 3 # Branch values: # * official release: nil From abacac918b59af6909918cd0fd018a2425d3b35b Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 12 Jun 2024 07:19:58 +0000 Subject: [PATCH 059/459] Add missing fixture journal_details to JournalsHelperTest (#40801). Patch by Mizuki ISHIKAWA (@ishikawa999). git-svn-id: https://svn.redmine.org/redmine/trunk@22874 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- test/helpers/journals_helper_test.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/helpers/journals_helper_test.rb b/test/helpers/journals_helper_test.rb index a33313e7853..55fb1260a44 100644 --- a/test/helpers/journals_helper_test.rb +++ b/test/helpers/journals_helper_test.rb @@ -29,7 +29,8 @@ class JournalsHelperTest < Redmine::HelperTest :enabled_modules, :custom_fields, :attachments, - :versions + :versions, + :journal_details def test_journal_thumbnail_attachments_should_return_thumbnailable_attachments skip unless convert_installed? From e41bc39322cae528d1c24256f6f404f5937d78ab Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 12 Jun 2024 09:39:06 +0000 Subject: [PATCH 060/459] Add LICENSE.txt in the root directory (#40202). git-svn-id: https://svn.redmine.org/redmine/trunk@22875 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- LICENSE.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000000..9184b333ddd --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,23 @@ +Redmine - project management software +Copyright (C) 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. + +For the full text of the license, please see the `COPYING` file +located in the `doc` directory. + +You can also find the full text of the GPL version 2 at the Free +Software Foundation's website at + +https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html + +or by writing to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. From b803bddb1f32842b0a5ec93640778d902b5f7999 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 12 Jun 2024 16:09:37 +0000 Subject: [PATCH 061/459] Fix "ArgumentError: Invalid response name: unprocessable_entity" with Rack 3.1.0+ in assert_response (#39889). Rack 3.1.0 changed the symbol for HTTP status code 422 from `:unprocessable_entity` to `:unprocessable_content`. Due to the change, `assert_response(:unprocessable_entity, ...)` raises ArgumentError with Rack 3.1.0+. This fix is a follow-up to r22837. git-svn-id: https://svn.redmine.org/redmine/trunk@22876 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- Gemfile | 1 + app/controllers/application_controller.rb | 2 +- app/controllers/boards_controller.rb | 2 +- app/controllers/custom_fields_controller.rb | 2 +- app/controllers/enumerations_controller.rb | 2 +- app/controllers/issue_statuses_controller.rb | 2 +- app/controllers/issues_controller.rb | 2 +- app/controllers/mail_handler_controller.rb | 2 +- app/controllers/members_controller.rb | 2 +- app/controllers/roles_controller.rb | 2 +- app/controllers/sys_controller.rb | 2 +- app/controllers/trackers_controller.rb | 2 +- app/controllers/users_controller.rb | 2 +- app/controllers/versions_controller.rb | 2 +- test/functional/issues_controller_test.rb | 2 +- test/functional/mail_handler_controller_test.rb | 2 +- test/functional/my_controller_test.rb | 2 +- test/functional/sys_controller_test.rb | 2 +- test/functional/users_controller_test.rb | 4 ++-- test/integration/api_test/attachments_test.rb | 4 ++-- test/integration/api_test/groups_test.rb | 6 +++--- test/integration/api_test/issue_categories_test.rb | 4 ++-- test/integration/api_test/issue_relations_test.rb | 2 +- test/integration/api_test/issues_test.rb | 14 +++++++------- test/integration/api_test/memberships_test.rb | 6 +++--- test/integration/api_test/my_test.rb | 4 ++-- test/integration/api_test/news_test.rb | 4 ++-- test/integration/api_test/projects_test.rb | 4 ++-- test/integration/api_test/repositories_test.rb | 4 ++-- test/integration/api_test/time_entries_test.rb | 6 +++--- test/integration/api_test/users_test.rb | 8 ++++---- test/integration/api_test/versions_test.rb | 2 +- test/integration/application_test.rb | 4 ++-- 33 files changed, 56 insertions(+), 55 deletions(-) diff --git a/Gemfile b/Gemfile index 101ee94e31d..746544262f8 100644 --- a/Gemfile +++ b/Gemfile @@ -15,6 +15,7 @@ gem 'rbpdf', '~> 1.21.3' gem 'addressable' gem 'rubyzip', '~> 2.3.0' gem 'propshaft', '~> 0.8.0' +gem 'rack', '>= 3.1.3' # Ruby Standard Gems gem 'csv', '~> 3.2.8' diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 51ea2e2fd0c..d7d588eb303 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -766,7 +766,7 @@ def render_validation_errors(objects) def render_api_errors(*messages) @error_messages = messages.flatten - render :template => 'common/error_messages', :format => [:api], :status => :unprocessable_entity, :layout => nil + render :template => 'common/error_messages', :format => [:api], :status => :unprocessable_content, :layout => nil end # Overrides #_include_layout? so that #render with no arguments diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb index 194f5b773dc..8798c818b1f 100644 --- a/app/controllers/boards_controller.rb +++ b/app/controllers/boards_controller.rb @@ -98,7 +98,7 @@ def update else respond_to do |format| format.html {render :action => 'edit'} - format.js {head :unprocessable_entity} + format.js {head :unprocessable_content} end end end diff --git a/app/controllers/custom_fields_controller.rb b/app/controllers/custom_fields_controller.rb index 68eeb6e1241..cb07c1f13b2 100644 --- a/app/controllers/custom_fields_controller.rb +++ b/app/controllers/custom_fields_controller.rb @@ -75,7 +75,7 @@ def update else respond_to do |format| format.html {render :action => 'edit'} - format.js {head :unprocessable_entity} + format.js {head :unprocessable_content} end end end diff --git a/app/controllers/enumerations_controller.rb b/app/controllers/enumerations_controller.rb index b4851f1e2c9..ed4d4817caf 100644 --- a/app/controllers/enumerations_controller.rb +++ b/app/controllers/enumerations_controller.rb @@ -70,7 +70,7 @@ def update else respond_to do |format| format.html {render :action => 'edit'} - format.js {head :unprocessable_entity} + format.js {head :unprocessable_content} end end end diff --git a/app/controllers/issue_statuses_controller.rb b/app/controllers/issue_statuses_controller.rb index 0d6e2199e48..e0dc2c704b0 100644 --- a/app/controllers/issue_statuses_controller.rb +++ b/app/controllers/issue_statuses_controller.rb @@ -66,7 +66,7 @@ def update else respond_to do |format| format.html {render :action => 'edit'} - format.js {head :unprocessable_entity} + format.js {head :unprocessable_content} end end end diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 8528a2fcace..5fbb0f7c291 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -84,7 +84,7 @@ def index else respond_to do |format| format.html {render :layout => !request.xhr?} - format.any(:atom, :csv, :pdf) {head :unprocessable_entity} + format.any(:atom, :csv, :pdf) {head :unprocessable_content} format.api {render_validation_errors(@query)} end end diff --git a/app/controllers/mail_handler_controller.rb b/app/controllers/mail_handler_controller.rb index bf871599e4a..79259565f5b 100644 --- a/app/controllers/mail_handler_controller.rb +++ b/app/controllers/mail_handler_controller.rb @@ -61,7 +61,7 @@ def index if MailHandler.safe_receive(email, options) head :created else - head :unprocessable_entity + head :unprocessable_content end end diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index 8d4f64bab43..3f7b376c60e 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -115,7 +115,7 @@ def destroy if @member.destroyed? render_api_ok else - head :unprocessable_entity + head :unprocessable_content end end end diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index f81144a5cf7..dfe7c2b8f73 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -90,7 +90,7 @@ def update else respond_to do |format| format.html {render :action => 'edit'} - format.js {head :unprocessable_entity} + format.js {head :unprocessable_content} end end end diff --git a/app/controllers/sys_controller.rb b/app/controllers/sys_controller.rb index 7e785f951c9..2ba7f998286 100644 --- a/app/controllers/sys_controller.rb +++ b/app/controllers/sys_controller.rb @@ -46,7 +46,7 @@ def create_project_repository if repository.save render :json => {repository.class.name.underscore.tr('/', '-') => {:id => repository.id, :url => repository.url}}, :status => :created else - head :unprocessable_entity + head :unprocessable_content end end end diff --git a/app/controllers/trackers_controller.rb b/app/controllers/trackers_controller.rb index 95cdcbc8fc9..c1415bc2c5d 100644 --- a/app/controllers/trackers_controller.rb +++ b/app/controllers/trackers_controller.rb @@ -81,7 +81,7 @@ def update edit render :action => 'edit' end - format.js {head :unprocessable_entity} + format.js {head :unprocessable_content} end end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 299c34c98b7..e32a8ddb85c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -81,7 +81,7 @@ def index else respond_to do |format| format.html {render :layout => !request.xhr?} - format.csv {head :unprocessable_entity} + format.csv {head :unprocessable_content} format.api {render_validation_errors(@query)} end end diff --git a/app/controllers/versions_controller.rb b/app/controllers/versions_controller.rb index fd74f5208b6..d52b43ba3a5 100644 --- a/app/controllers/versions_controller.rb +++ b/app/controllers/versions_controller.rb @@ -165,7 +165,7 @@ def destroy flash[:error] = l(:notice_unable_delete_version) redirect_to settings_project_path(@project, :tab => 'versions') end - format.api {head :unprocessable_entity} + format.api {head :unprocessable_content} end end end diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index ca09ee8f11b..fbdae416355 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -4748,7 +4748,7 @@ def test_create_without_project_id_should_be_denied_without_permission } } ) - assert_response :unprocessable_entity + assert_response :unprocessable_content end end diff --git a/test/functional/mail_handler_controller_test.rb b/test/functional/mail_handler_controller_test.rb index 3227fe5cada..16eb1fbe22e 100644 --- a/test/functional/mail_handler_controller_test.rb +++ b/test/functional/mail_handler_controller_test.rb @@ -117,7 +117,7 @@ def test_should_respond_with_422_if_not_created ) end end - assert_response :unprocessable_entity + assert_response :unprocessable_content end def test_should_not_allow_with_api_disabled diff --git a/test/functional/my_controller_test.rb b/test/functional/my_controller_test.rb index da16e7c50ad..b485b5c9aa1 100644 --- a/test/functional/my_controller_test.rb +++ b/test/functional/my_controller_test.rb @@ -730,7 +730,7 @@ def test_add_invalid_block_should_error :block => 'invalid' } ) - assert_response :unprocessable_entity + assert_response :unprocessable_content end def test_remove_block diff --git a/test/functional/sys_controller_test.rb b/test/functional/sys_controller_test.rb index fb116b4d984..17e03b133bf 100644 --- a/test/functional/sys_controller_test.rb +++ b/test/functional/sys_controller_test.rb @@ -95,7 +95,7 @@ def test_create_with_failure :repository => {:url => 'invalid url'} } ) - assert_response :unprocessable_entity + assert_response :unprocessable_content end def test_fetch_changesets diff --git a/test/functional/users_controller_test.rb b/test/functional/users_controller_test.rb index 5d6e6b754fb..b869db0d09f 100644 --- a/test/functional/users_controller_test.rb +++ b/test/functional/users_controller_test.rb @@ -1114,7 +1114,7 @@ def test_destroy_without_unsubscribe_is_denied assert_no_difference 'User.count' do delete :destroy, params: {id: user.id} end - assert_response :unprocessable_entity + assert_response :unprocessable_content end end @@ -1125,7 +1125,7 @@ def test_destroy_last_admin_is_denied assert_no_difference 'User.count' do delete :destroy, params: {id: user.id} end - assert_response :unprocessable_entity + assert_response :unprocessable_content end end diff --git a/test/integration/api_test/attachments_test.rb b/test/integration/api_test/attachments_test.rb index 4bb40a3021d..a3d4ef21abb 100644 --- a/test/integration/api_test/attachments_test.rb +++ b/test/integration/api_test/attachments_test.rb @@ -118,7 +118,7 @@ def teardown :params => {:attachment => {:filename => '', :description => 'updated'}}, :headers => credentials('jsmith') ) - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/json', response.media_type json = ActiveSupport::JSON.decode(response.body) assert_include "File cannot be blank", json['errors'] @@ -224,7 +224,7 @@ def teardown "CONTENT_TYPE" => 'application/octet-stream' }.merge(credentials('jsmith')) ) - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_select 'error', :text => /exceeds the maximum allowed file size/ end end diff --git a/test/integration/api_test/groups_test.rb b/test/integration/api_test/groups_test.rb index 8e57d8352ed..fa4cbb205ac 100644 --- a/test/integration/api_test/groups_test.rb +++ b/test/integration/api_test/groups_test.rb @@ -150,7 +150,7 @@ class Redmine::ApiTest::GroupsTest < Redmine::ApiTest::Base :headers => credentials('admin') ) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', response.media_type assert_select 'errors' do @@ -179,7 +179,7 @@ class Redmine::ApiTest::GroupsTest < Redmine::ApiTest::Base :params => {:group => {:name => ''}}, :headers => credentials('admin') ) - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', response.media_type assert_select 'errors' do @@ -220,7 +220,7 @@ class Redmine::ApiTest::GroupsTest < Redmine::ApiTest::Base :params => {:user_id => 5}, :headers => credentials('admin') ) - assert_response :unprocessable_entity + assert_response :unprocessable_content end assert_select 'errors' do diff --git a/test/integration/api_test/issue_categories_test.rb b/test/integration/api_test/issue_categories_test.rb index 1de78cd9040..676c8d01353 100644 --- a/test/integration/api_test/issue_categories_test.rb +++ b/test/integration/api_test/issue_categories_test.rb @@ -62,7 +62,7 @@ class Redmine::ApiTest::IssueCategoriesTest < Redmine::ApiTest::Base :params => {:issue_category => {:name => ''}}, :headers => credentials('jsmith')) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "Name cannot be blank" @@ -87,7 +87,7 @@ class Redmine::ApiTest::IssueCategoriesTest < Redmine::ApiTest::Base :params => {:issue_category => {:name => ''}}, :headers => credentials('jsmith')) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "Name cannot be blank" diff --git a/test/integration/api_test/issue_relations_test.rb b/test/integration/api_test/issue_relations_test.rb index 9189875b27d..3ac12e276cd 100644 --- a/test/integration/api_test/issue_relations_test.rb +++ b/test/integration/api_test/issue_relations_test.rb @@ -87,7 +87,7 @@ class Redmine::ApiTest::IssueRelationsTest < Redmine::ApiTest::Base ) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_select 'errors error', :text => /Relation type is not included in the list/ end diff --git a/test/integration/api_test/issues_test.rb b/test/integration/api_test/issues_test.rb index 142dc86b834..84abe70ed88 100644 --- a/test/integration/api_test/issues_test.rb +++ b/test/integration/api_test/issues_test.rb @@ -105,7 +105,7 @@ class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base test "GET /issues.xml with invalid query params" do get '/issues.xml', :params => {:f => ['start_date'], :op => {:start_date => '='}} - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "Start date cannot be blank" end @@ -725,7 +725,7 @@ def test_show_should_include_issue_attributes '/issues.json', :params => {:issue => {:project_id => 999, :subject => "API"}}, :headers => credentials('jsmith')) - assert_response :unprocessable_entity + assert_response :unprocessable_content end test "POST /issues.json with invalid project_id and any assigned_to_id should respond with 422" do @@ -739,7 +739,7 @@ def test_show_should_include_issue_attributes } }, :headers => credentials('jsmith')) - assert_response :unprocessable_entity + assert_response :unprocessable_content end test "POST /issues.json with invalid project_id and any fixed_version_id should respond with 422" do @@ -753,7 +753,7 @@ def test_show_should_include_issue_attributes } }, :headers => credentials('jsmith')) - assert_response :unprocessable_entity + assert_response :unprocessable_content end test "PUT /issues/:id.xml" do @@ -885,7 +885,7 @@ def test_show_should_include_issue_attributes '/issues/6.xml', :params => {:issue => {:subject => ''}}, :headers => credentials('jsmith')) - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_select 'errors error', :text => "Subject cannot be blank" end @@ -895,7 +895,7 @@ def test_show_should_include_issue_attributes '/issues/6.xml', :params => {:issue => {:assigned_to_id => user.id}}, :headers => credentials('jsmith')) - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_select 'errors error', :text => "Assignee is invalid" end @@ -920,7 +920,7 @@ def test_show_should_include_issue_attributes '/issues/6.json', :params => {:issue => {:subject => ''}}, :headers => credentials('jsmith')) - assert_response :unprocessable_entity + assert_response :unprocessable_content json = ActiveSupport::JSON.decode(response.body) assert json['errors'].include?("Subject cannot be blank") end diff --git a/test/integration/api_test/memberships_test.rb b/test/integration/api_test/memberships_test.rb index 3346e844d20..0b7c706081e 100644 --- a/test/integration/api_test/memberships_test.rb +++ b/test/integration/api_test/memberships_test.rb @@ -101,7 +101,7 @@ class Redmine::ApiTest::MembershipsTest < Redmine::ApiTest::Base :params => {:membership => {:role_ids => [2, 3]}}, :headers => credentials('jsmith') ) - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => 'User or Group cannot be blank' end @@ -158,7 +158,7 @@ class Redmine::ApiTest::MembershipsTest < Redmine::ApiTest::Base :params => {:membership => {:user_id => 3, :role_ids => [99]}}, :headers => credentials('jsmith') ) - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "Role cannot be empty" end @@ -179,7 +179,7 @@ class Redmine::ApiTest::MembershipsTest < Redmine::ApiTest::Base Member.find(2).member_roles.first.update_attribute :inherited_from, 99 delete '/memberships/2.xml', :headers => credentials('jsmith') - assert_response :unprocessable_entity + assert_response :unprocessable_content end end end diff --git a/test/integration/api_test/my_test.rb b/test/integration/api_test/my_test.rb index e84d9d61923..81a952b2e23 100644 --- a/test/integration/api_test/my_test.rb +++ b/test/integration/api_test/my_test.rb @@ -81,7 +81,7 @@ class Redmine::ApiTest::MyTest < Redmine::ApiTest::Base } }, :headers => credentials('dlopper', 'foo')) - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "First name cannot be blank" end @@ -95,7 +95,7 @@ class Redmine::ApiTest::MyTest < Redmine::ApiTest::Base } }, :headers => credentials('dlopper', 'foo')) - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/json', @response.media_type json = ActiveSupport::JSON.decode(response.body) assert_kind_of Hash, json diff --git a/test/integration/api_test/news_test.rb b/test/integration/api_test/news_test.rb index ee802e1030d..1a3bb824e26 100644 --- a/test/integration/api_test/news_test.rb +++ b/test/integration/api_test/news_test.rb @@ -310,7 +310,7 @@ class Redmine::ApiTest::NewsTest < Redmine::ApiTest::Base '/news/1.xml', :params => {:news => {:title => ''}}, :headers => credentials('jsmith')) - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_select 'errors error', :text => "Title cannot be blank" end @@ -319,7 +319,7 @@ class Redmine::ApiTest::NewsTest < Redmine::ApiTest::Base '/news/1.json', :params => {:news => {:title => ''}}, :headers => credentials('jsmith')) - assert_response :unprocessable_entity + assert_response :unprocessable_content json = ActiveSupport::JSON.decode(response.body) assert json['errors'].include?("Title cannot be blank") end diff --git a/test/integration/api_test/projects_test.rb b/test/integration/api_test/projects_test.rb index 1ab995d4527..d1dd6c24adb 100644 --- a/test/integration/api_test/projects_test.rb +++ b/test/integration/api_test/projects_test.rb @@ -304,7 +304,7 @@ def test_get_project_should_not_load_default_query ) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "Identifier cannot be blank" end @@ -366,7 +366,7 @@ def test_get_project_should_not_load_default_query ) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "Name cannot be blank" end diff --git a/test/integration/api_test/repositories_test.rb b/test/integration/api_test/repositories_test.rb index c35023b60ab..ae59cd8ca58 100644 --- a/test/integration/api_test/repositories_test.rb +++ b/test/integration/api_test/repositories_test.rb @@ -70,7 +70,7 @@ class Redmine::ApiTest::RepositoriesTest < Redmine::ApiTest::Base assert_no_difference 'Changeset.find(103).issues.size' do post '/projects/1/repository/10/revisions/4/issues.xml', :headers => credentials('jsmith'), :params => {:issue_id => '9999'} end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_select 'errors error', :text => 'Issue is invalid' end @@ -78,7 +78,7 @@ class Redmine::ApiTest::RepositoriesTest < Redmine::ApiTest::Base assert_no_difference 'Changeset.find(103).issues.size' do post '/projects/1/repository/10/revisions/4/issues.json', :headers => credentials('jsmith'), :params => {:issue_id => '9999'} end - assert_response :unprocessable_entity + assert_response :unprocessable_content json = ActiveSupport::JSON.decode(response.body) assert json['errors'].include?('Issue is invalid') end diff --git a/test/integration/api_test/time_entries_test.rb b/test/integration/api_test/time_entries_test.rb index f2c38d80bc9..bd417ab2dad 100644 --- a/test/integration/api_test/time_entries_test.rb +++ b/test/integration/api_test/time_entries_test.rb @@ -141,7 +141,7 @@ class Redmine::ApiTest::TimeEntriesTest < Redmine::ApiTest::Base :params => {:time_entry => {:project_id => '1', :spent_on => '2010-12-02', :activity_id => '11'}}, :headers => credentials('jsmith')) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "Hours cannot be blank" @@ -200,7 +200,7 @@ class Redmine::ApiTest::TimeEntriesTest < Redmine::ApiTest::Base :params => {:time_entry => {:hours => '', :comments => 'API Update'}}, :headers => credentials('jsmith')) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "Hours cannot be blank" @@ -229,7 +229,7 @@ class Redmine::ApiTest::TimeEntriesTest < Redmine::ApiTest::Base assert_no_difference 'TimeEntry.count' do delete '/time_entries/2.xml', :headers => credentials('jsmith') end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors' end diff --git a/test/integration/api_test/users_test.rb b/test/integration/api_test/users_test.rb index 183dd3af9aa..27772be29b4 100644 --- a/test/integration/api_test/users_test.rb +++ b/test/integration/api_test/users_test.rb @@ -417,7 +417,7 @@ class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base :headers => credentials('admin')) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "First name cannot be blank" end @@ -434,7 +434,7 @@ class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base :headers => credentials('admin')) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/json', @response.media_type json = ActiveSupport::JSON.decode(response.body) assert_kind_of Hash, json @@ -503,7 +503,7 @@ class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base :headers => credentials('admin')) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/xml', @response.media_type assert_select 'errors error', :text => "First name cannot be blank" end @@ -521,7 +521,7 @@ class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base :headers => credentials('admin')) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal 'application/json', @response.media_type json = ActiveSupport::JSON.decode(response.body) assert_kind_of Hash, json diff --git a/test/integration/api_test/versions_test.rb b/test/integration/api_test/versions_test.rb index 614d98950f4..96d70095c59 100644 --- a/test/integration/api_test/versions_test.rb +++ b/test/integration/api_test/versions_test.rb @@ -120,7 +120,7 @@ class Redmine::ApiTest::VersionsTest < Redmine::ApiTest::Base :params => {:version => {:name => ''}}, :headers => credentials('jsmith')) end - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_select 'errors error', :text => "Name cannot be blank" end diff --git a/test/integration/application_test.rb b/test/integration/application_test.rb index 7f077b57174..77c96d89bf7 100644 --- a/test/integration/application_test.rb +++ b/test/integration/application_test.rb @@ -73,7 +73,7 @@ def test_missing_template_should_respond_with_4xx def test_invalid_token_should_call_custom_handler ActionController::Base.allow_forgery_protection = true post '/issues' - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_include "Invalid form authenticity token.", response.body ensure ActionController::Base.allow_forgery_protection = false @@ -83,7 +83,7 @@ def test_localization_should_be_set_correctly_on_invalid_token ActionController::Base.allow_forgery_protection = true Setting.default_language = 'en' post '/issues', :headers => {'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'} - assert_response :unprocessable_entity + assert_response :unprocessable_content assert_equal :fr, current_language assert_select "html[lang=?]", "fr" ensure From af6a627d205fba99a8bda29b0e0bfea0a766506e Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Thu, 13 Jun 2024 03:06:04 +0000 Subject: [PATCH 062/459] Revisions count is wrong on the wiki content page (#40655). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contributed by Karel Pičman (@picman). git-svn-id: https://svn.redmine.org/redmine/trunk@22877 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/views/wiki/show.html.erb | 2 +- test/functional/wiki_controller_test.rb | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/views/wiki/show.html.erb b/app/views/wiki/show.html.erb index 6a024580944..be0d7355a37 100644 --- a/app/views/wiki/show.html.erb +++ b/app/views/wiki/show.html.erb @@ -85,7 +85,7 @@

<% if User.current.allowed_to?(:view_wiki_edits, @project) %> <%= wiki_content_update_info(@content) %> - · <%= link_to l(:label_x_revisions, :count => @content.version), {:action => 'history', :id => @page.title} %> + · <%= link_to l(:label_x_revisions, :count => @page.content.versions.size), {:action => 'history', :id => @page.title} %> <% end %> <% if @page.protected? %> <%= l('status_locked') %> diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb index d7e9676f825..be62dcc8e3e 100644 --- a/test/functional/wiki_controller_test.rb +++ b/test/functional/wiki_controller_test.rb @@ -233,6 +233,20 @@ def test_show_protected_page_shoud_show_locked_badge end end + def test_show_should_display_revisions_count + # To ensure that the number of versions is correctly displayed instead of + # the last version number of the wiki page, make a situation where the + # those two numbers are different. + content_versions = WikiContentVersion.where(page_id: 1) + content_versions.first.destroy + assert 3, content_versions.last.version + assert 2, content_versions.size + + get :show, :params => {:project_id => 1, :id => 'CookBook_documentation'} + assert_response :success + assert_select 'a[href=?]', '/projects/1/wiki/CookBook_documentation/history', :text => /2 revisions/ + end + def test_get_new @request.session[:user_id] = 2 From b6fe86477033f8994e21f11ba4054908b2002fab Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Mon, 17 Jun 2024 02:22:50 +0000 Subject: [PATCH 063/459] Update MiniMagick to 4.13 (#40849). git-svn-id: https://svn.redmine.org/redmine/trunk@22878 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 746544262f8..980261bc9fa 100644 --- a/Gemfile +++ b/Gemfile @@ -41,7 +41,7 @@ end # Optional gem for exporting the gantt to a PNG file group :minimagick do - gem 'mini_magick', '~> 4.12.0' + gem 'mini_magick', '~> 4.13.0' end # Optional Markdown support From ddde0ff47dbbc8d270e4f3bd77fa3a898fc013a2 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Mon, 17 Jun 2024 03:11:08 +0000 Subject: [PATCH 064/459] Fix RuboCop offense Rails/ActiveRecordCallbacksOrder (#39889). git-svn-id: https://svn.redmine.org/redmine/trunk@22879 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- .rubocop_todo.yml | 19 +------------------ app/models/attachment.rb | 2 +- app/models/change.rb | 2 +- app/models/changeset.rb | 2 +- app/models/enumeration.rb | 2 +- app/models/issue.rb | 6 +++--- app/models/issue_status.rb | 2 +- app/models/member_role.rb | 2 +- app/models/project.rb | 6 +++--- app/models/user.rb | 4 ++-- app/models/version.rb | 2 +- app/models/wiki_page.rb | 2 +- 12 files changed, 17 insertions(+), 34 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 2f7eb1c7870..05932e9156f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --exclude-limit 20 --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.64.0. +# using RuboCop version 1.64.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -454,23 +454,6 @@ Naming/VariableNumber: - 'test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb' - 'test/unit/project_test.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: Include. -# Include: app/models/**/*.rb -Rails/ActiveRecordCallbacksOrder: - Exclude: - - 'app/models/attachment.rb' - - 'app/models/change.rb' - - 'app/models/changeset.rb' - - 'app/models/enumeration.rb' - - 'app/models/issue.rb' - - 'app/models/issue_status.rb' - - 'app/models/member_role.rb' - - 'app/models/project.rb' - - 'app/models/user.rb' - - 'app/models/version.rb' - - 'app/models/wiki_page.rb' - # Configuration parameters: Severity, Include. # Include: app/models/**/*.rb Rails/ActiveRecordOverride: diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 59addf5281c..7fc8a8ab03c 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -84,9 +84,9 @@ class Attachment < ApplicationRecord @@thumbnails_storage_path = File.join(Rails.root, "tmp", "thumbnails") before_create :files_to_final_location - after_rollback :delete_from_disk, :on => :create after_commit :delete_from_disk, :on => :destroy after_commit :reuse_existing_file_if_possible, :on => :create + after_rollback :delete_from_disk, :on => :create safe_attributes 'filename', 'content_type', 'description' diff --git a/app/models/change.rb b/app/models/change.rb index f512ad036d0..c7edd166865 100644 --- a/app/models/change.rb +++ b/app/models/change.rb @@ -21,8 +21,8 @@ class Change < ApplicationRecord belongs_to :changeset validates_presence_of :changeset_id, :action, :path - before_save :init_path before_validation :replace_invalid_utf8_of_path + before_save :init_path def replace_invalid_utf8_of_path self.path = Redmine::CodesetUtil.replace_invalid_utf8(self.path) diff --git a/app/models/changeset.rb b/app/models/changeset.rb index d8ce4475be5..40e6cf51c6a 100644 --- a/app/models/changeset.rb +++ b/app/models/changeset.rb @@ -60,8 +60,8 @@ class Changeset < ApplicationRecord where(Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args)) end) - after_create :scan_for_issues before_create :before_create_cs + after_create :scan_for_issues def revision=(r) write_attribute :revision, (r.nil? ? nil : r.to_s) diff --git a/app/models/enumeration.rb b/app/models/enumeration.rb index c96c18c98b6..b97e97e9d5a 100644 --- a/app/models/enumeration.rb +++ b/app/models/enumeration.rb @@ -28,8 +28,8 @@ class Enumeration < ApplicationRecord acts_as_customizable acts_as_tree - before_destroy :check_integrity before_save :check_default + before_destroy :check_integrity after_save :update_children_name validates_presence_of :name diff --git a/app/models/issue.rb b/app/models/issue.rb index fdca171c991..95e5a4f246b 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -21,6 +21,8 @@ class Issue < ApplicationRecord include Redmine::SafeAttributes include Redmine::Utils::DateCalculation include Redmine::I18n + before_validation :default_assign, on: :create + before_validation :clear_disabled_fields before_save :set_parent_id include Redmine::NestedSet::IssueNestedSet @@ -107,8 +109,6 @@ class Issue < ApplicationRecord end end) - before_validation :default_assign, on: :create - before_validation :clear_disabled_fields before_save :close_duplicates, :update_done_ratio_from_issue_status, :force_updated_on_change, :update_closed_on after_save do |issue| @@ -116,11 +116,11 @@ class Issue < ApplicationRecord issue.send :after_project_change end end + after_destroy :update_parent_attributes after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :delete_selected_attachments, :create_journal # Should be after_create but would be called before previous after_save callbacks after_save :after_create_from_copy - after_destroy :update_parent_attributes # add_auto_watcher needs to run before sending notifications, thus it needs # to be added after send_notification (after_ callbacks are run in inverse order) # https://api.rubyonrails.org/v5.2.3/classes/ActiveSupport/Callbacks/ClassMethods.html#method-i-set_callback diff --git a/app/models/issue_status.rb b/app/models/issue_status.rb index 7fb0ce00799..eb2e488f8d3 100644 --- a/app/models/issue_status.rb +++ b/app/models/issue_status.rb @@ -20,12 +20,12 @@ class IssueStatus < ApplicationRecord include Redmine::SafeAttributes + after_update :handle_is_closed_change before_destroy :check_integrity has_many :workflows, :class_name => 'WorkflowTransition', :foreign_key => "old_status_id" has_many :workflow_transitions_as_new_status, :class_name => 'WorkflowTransition', :foreign_key => "new_status_id" acts_as_positioned - after_update :handle_is_closed_change before_destroy :delete_workflow_rules validates_presence_of :name diff --git a/app/models/member_role.rb b/app/models/member_role.rb index 11f1a04e7e7..975c6f2b030 100644 --- a/app/models/member_role.rb +++ b/app/models/member_role.rb @@ -21,9 +21,9 @@ class MemberRole < ApplicationRecord belongs_to :member belongs_to :role + after_create :add_role_to_group_users, :add_role_to_subprojects after_destroy :remove_member_if_empty - after_create :add_role_to_group_users, :add_role_to_subprojects after_destroy :remove_inherited_roles validates_presence_of :role diff --git a/app/models/project.rb b/app/models/project.rb index 09927b4cc56..42499ae5879 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -87,13 +87,13 @@ class Project < ApplicationRecord validates_exclusion_of :identifier, :in => %w(new) validate :validate_parent + after_update :update_versions_from_hierarchy_change, + :if => proc {|project| project.saved_change_to_parent_id?} + before_destroy :delete_all_members after_save :update_inherited_members, :if => proc {|project| project.saved_change_to_inherit_members?} after_save :remove_inherited_member_roles, :add_inherited_member_roles, :if => proc {|project| project.saved_change_to_parent_id?} - after_update :update_versions_from_hierarchy_change, - :if => proc {|project| project.saved_change_to_parent_id?} - before_destroy :delete_all_members scope :has_module, (lambda do |mod| where("#{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name=?)", mod.to_s) diff --git a/app/models/user.rb b/app/models/user.rb index 4d78070d004..6e364c5c173 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -126,11 +126,11 @@ class User < Principal self.valid_statuses = [STATUS_ACTIVE, STATUS_REGISTERED, STATUS_LOCKED] before_validation :instantiate_email_address - before_create :set_mail_notification before_save :generate_password_if_needed, :update_hashed_password + before_create :set_mail_notification before_destroy :remove_references_before_destroy - after_save :update_notified_project_ids, :destroy_tokens, :deliver_security_notification after_destroy :deliver_security_notification + after_save :update_notified_project_ids, :destroy_tokens, :deliver_security_notification scope :admin, (lambda do |*args| admin = args.size > 0 ? !!args.first : true diff --git a/app/models/version.rb b/app/models/version.rb index eed2e22d76b..7434f0c32a1 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -123,8 +123,8 @@ class Version < ApplicationRecord include Redmine::SafeAttributes after_update :update_issues_from_sharing_change - after_save :update_default_project_version before_destroy :nullify_projects_default_version + after_save :update_default_project_version belongs_to :project has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify, :extend => FixedIssuesExtension diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index cf23612c0f1..d76e288d863 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -58,8 +58,8 @@ class WikiPage < ApplicationRecord validates_associated :content validate :validate_parent_title - before_destroy :delete_redirects before_save :handle_rename_or_move, :update_wiki_start_page + before_destroy :delete_redirects after_save :handle_children_move, :delete_selected_attachments # eager load information about last updates, without loading text From c132b178a1cb47a6f4f754c341a3326dc1fc7b14 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Mon, 17 Jun 2024 06:55:36 +0000 Subject: [PATCH 065/459] Optimize Version model by reducing redundant SQL count queries (#40798). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22880 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/version.rb | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/app/models/version.rb b/app/models/version.rb index 7434f0c32a1..c12420c3fab 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -45,22 +45,17 @@ def closed_count # Returns the completion percentage of this version based on the amount of open/closed issues # and the time spent on the open issues. def completed_percent - if count == 0 - 0 - elsif open_count == 0 - 100 - else - issues_progress(false) + issues_progress(true) - end + return 0 if open_count + closed_count == 0 + return 100 if open_count == 0 + + issues_progress(false) + issues_progress(true) end # Returns the percentage of issues that have been marked as 'closed'. def closed_percent - if count == 0 - 0 - else - issues_progress(false) - end + return 0 if open_count + closed_count == 0 + + issues_progress(false) end private @@ -105,14 +100,15 @@ def issues_progress(open) @issues_progress ||= {} @issues_progress[open] ||= begin progress = 0 - if count > 0 + issues_count = open_count + closed_count + if issues_count > 0 done = self.open(open).sum do |c| estimated = c.total_estimated_hours.to_f estimated = estimated_average unless estimated > 0.0 ratio = c.closed? ? 100 : (c.done_ratio || 0) estimated * ratio end - progress = done / (estimated_average * count) + progress = done / (estimated_average * issues_count) end progress end From 35aa00f7ac70031e9857a3f8ebcf043d4db16dca Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Mon, 17 Jun 2024 06:57:57 +0000 Subject: [PATCH 066/459] Optimize FixedIssuesExtension#closed_percent by bypassing issues_progress when all issues are closed (#40798). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22881 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/version.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/version.rb b/app/models/version.rb index c12420c3fab..f485bae5f6b 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -54,6 +54,7 @@ def completed_percent # Returns the percentage of issues that have been marked as 'closed'. def closed_percent return 0 if open_count + closed_count == 0 + return 100 if open_count == 0 issues_progress(false) end From b3308d126a458d2b68cdb855a7c93d43335899e9 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Mon, 17 Jun 2024 07:10:29 +0000 Subject: [PATCH 067/459] Optimize Version#behind_schedule? by avoiding the call to completed_percent when due_date or start_date is nil (#40798). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22882 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/version.rb | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/app/models/version.rb b/app/models/version.rb index f485bae5f6b..b6137d352b6 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -269,14 +269,11 @@ def completed? end def behind_schedule? - if completed_percent == 100 - return false - elsif due_date && start_date - done_date = start_date + ((due_date - start_date+1)* completed_percent/100).floor - return done_date <= User.current.today - else - false # No issues so it's not late - end + # Blank due date, no issues, or 100% completed, so it's not late + return false if due_date.nil? || start_date.nil? || completed_percent == 100 + + done_date = start_date + ((due_date - start_date + 1) * completed_percent / 100).floor + done_date <= User.current.today end # Returns the completion percentage of this version based on the amount of open/closed issues From 07307140b97ef8de5a952ae06ddc674bdc2b3f45 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 19 Jun 2024 14:06:08 +0000 Subject: [PATCH 068/459] Fix misalignment issue when displaying the table of contents (TOC) on the right of wiki page (#34473). Patch by Mizuki ISHIKAWA (@ishikawa999). git-svn-id: https://svn.redmine.org/redmine/trunk@22885 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/assets/stylesheets/application.css | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 2d82fba7d20..8ab85f26985 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -1405,8 +1405,10 @@ div.wiki ul.toc { } * html div.wiki ul.toc { width: 50%; } /* IE6 doesn't autosize div */ -div.wiki ul.toc.right { float: right; margin-left: 12px; margin-right: 0; width: auto; } -div.wiki ul.toc.left { float: left; margin-right: 12px; margin-left: 0; width: auto; } +div.wiki ul.toc.right { float: right; margin-left: 12px; margin-right: 0; width: auto; clear: right +;} +div.wiki ul.toc.left { float: left; margin-right: 12px; margin-left: 0; width: auto; clear: left + ; } div.wiki ul.toc ul { margin: 0; padding: 0; } div.wiki ul.toc li {list-style-type:none; margin: 0; font-size:12px;} div.wiki ul.toc>li:first-child {margin-bottom: .5em; color: #777;} From 5a96997f6a839d09fe9b22fd1f26d50b766da3e8 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Wed, 19 Jun 2024 14:27:20 +0000 Subject: [PATCH 069/459] Support multiple multi-word phrases in the search engine (#38446). Patch by Go MAEDA (@maeda). git-svn-id: https://svn.redmine.org/redmine/trunk@22886 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/search.rb | 6 +++++- test/unit/lib/redmine/search_test.rb | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/redmine/search.rb b/lib/redmine/search.rb index c07f93aad1f..6c3ee835c8b 100644 --- a/lib/redmine/search.rb +++ b/lib/redmine/search.rb @@ -135,7 +135,11 @@ def initialize(question) def tokens # extract tokens from the question # eg. hello "bye bye" => ["hello", "bye bye"] - tokens = @question.scan(%r{(([[:space:]]|^)"[^"]+"([[:space:]]|$)|[[:^space:]]+)}).collect {|m| m.first.gsub(%r{(^[[:space:]]*"[[:space:]]*|[[:space:]]*"[[:space:]]*$)}, '')} + tokens = @question.scan(/"[^"]+"|[^\p{Zs}]+/).map do |token| + # Remove quotes from quoted tokens, strip surrounding whitespace + # e.g. "\" foo bar \"" => "foo bar" + token.gsub(/\A"\p{Zs}*|\p{Zs}*"\Z/, '') + end # tokens must be at least 2 characters long # but for Chinese characters (Chinese HANZI/Japanese KANJI), tokens can be one character # no more than 5 tokens to search for diff --git a/test/unit/lib/redmine/search_test.rb b/test/unit/lib/redmine/search_test.rb index 72cf1449269..e2d77cca046 100644 --- a/test/unit/lib/redmine/search_test.rb +++ b/test/unit/lib/redmine/search_test.rb @@ -30,4 +30,9 @@ def test_tokenize_should_consider_ideographic_space_as_separator value = "全角\u3000スペース" assert_equal %w[全角 スペース], Redmine::Search::Tokenizer.new(value).tokens end + + def test_tokenize_should_support_multiple_phrases + value = '"phrase one" "phrase two"' + assert_equal ["phrase one", "phrase two"], Redmine::Search::Tokenizer.new(value).tokens + end end From 2706019f09f657675506c977ce1fd49750185108 Mon Sep 17 00:00:00 2001 From: Go MAEDA Date: Thu, 20 Jun 2024 04:11:39 +0000 Subject: [PATCH 070/459] Upgrade jQuery to 3.7.1 and jQuery UI to 1.13.3 (#40853, #40864). git-svn-id: https://svn.redmine.org/redmine/trunk@22887 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/assets/javascripts/jquery-3.6.1-ui-1.13.2.js | 9 --------- app/assets/javascripts/jquery-3.7.1-ui-1.13.3.js | 8 ++++++++ app/helpers/application_helper.rb | 5 +++-- 3 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 app/assets/javascripts/jquery-3.6.1-ui-1.13.2.js create mode 100644 app/assets/javascripts/jquery-3.7.1-ui-1.13.3.js diff --git a/app/assets/javascripts/jquery-3.6.1-ui-1.13.2.js b/app/assets/javascripts/jquery-3.6.1-ui-1.13.2.js deleted file mode 100644 index 13004fad67a..00000000000 --- a/app/assets/javascripts/jquery-3.6.1-ui-1.13.2.js +++ /dev/null @@ -1,9 +0,0 @@ -/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="

",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=V(e||this.defaultElement||this)[0],this.element=V(e),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=V(),this.hoverable=V(),this.focusable=V(),this.classesElementLookup={},e!==this&&(V.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===e&&this.destroy()}}),this.document=V(e.style?e.ownerDocument:e.document||e),this.window=V(this.document[0].defaultView||this.document[0].parentWindow)),this.options=V.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:V.noop,_create:V.noop,_init:V.noop,destroy:function(){var i=this;this._destroy(),V.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:V.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return V.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t]=V.widget.extend({},this.options[t]),n=0;n
"),i=e.children()[0];return V("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i},getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.widthx(k(s),k(n))?o.important="horizontal":o.important="vertical",u.using.call(this,t,o)}),a.offset(V.extend(h,{using:t}))})},V.ui.position={fit:{left:function(t,e){var i=e.within,s=i.isWindow?i.scrollLeft:i.offset.left,n=i.width,o=t.left-e.collisionPosition.marginLeft,a=s-o,r=o+e.collisionWidth-n-s;e.collisionWidth>n?0n?0")[0],w=d.each;function P(t){return null==t?t+"":"object"==typeof t?p[e.call(t)]||"object":typeof t}function M(t,e,i){var s=v[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:Math.min(s.max,Math.max(0,t)))}function S(s){var n=m(),o=n._rgba=[];return s=s.toLowerCase(),w(g,function(t,e){var i=e.re.exec(s),i=i&&e.parse(i),e=e.space||"rgba";if(i)return i=n[e](i),n[_[e].cache]=i[_[e].cache],o=n._rgba=i._rgba,!1}),o.length?("0,0,0,0"===o.join()&&d.extend(o,B.transparent),n):B[s]}function H(t,e,i){return 6*(i=(i+1)%1)<1?t+(e-t)*i*6:2*i<1?e:3*i<2?t+(e-t)*(2/3-i)*6:t}y.style.cssText="background-color:rgba(1,1,1,.5)",b.rgba=-1o.mod/2?s+=o.mod:s-n>o.mod/2&&(s-=o.mod)),l[i]=M((n-s)*a+s,e)))}),this[e](l)},blend:function(t){if(1===this._rgba[3])return this;var e=this._rgba.slice(),i=e.pop(),s=m(t)._rgba;return m(d.map(e,function(t,e){return(1-i)*s[e]+i*t}))},toRgbaString:function(){var t="rgba(",e=d.map(this._rgba,function(t,e){return null!=t?t:2").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e={width:i.width(),height:i.height()},n=document.activeElement;try{n.id}catch(t){n=document.body}return i.wrap(t),i[0]!==n&&!V.contains(i[0],n)||V(n).trigger("focus"),t=i.parent(),"static"===i.css("position")?(t.css({position:"relative"}),i.css({position:"relative"})):(V.extend(s,{position:i.css("position"),zIndex:i.css("z-index")}),V.each(["top","left","bottom","right"],function(t,e){s[e]=i.css(e),isNaN(parseInt(s[e],10))&&(s[e]="auto")}),i.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),i.css(e),t.css(s).show()},removeWrapper:function(t){var e=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),t[0]!==e&&!V.contains(t[0],e)||V(e).trigger("focus")),t}}),V.extend(V.effects,{version:"1.13.2",define:function(t,e,i){return i||(i=e,e="effect"),V.effects.effect[t]=i,V.effects.effect[t].mode=e,i},scaledDimensions:function(t,e,i){if(0===e)return{height:0,width:0,outerHeight:0,outerWidth:0};var s="horizontal"!==i?(e||100)/100:1,e="vertical"!==i?(e||100)/100:1;return{height:t.height()*e,width:t.width()*s,outerHeight:t.outerHeight()*e,outerWidth:t.outerWidth()*s}},clipToBox:function(t){return{width:t.clip.right-t.clip.left,height:t.clip.bottom-t.clip.top,left:t.clip.left,top:t.clip.top}},unshift:function(t,e,i){var s=t.queue();1").insertAfter(t).css({display:/^(inline|ruby)/.test(t.css("display"))?"inline-block":"block",visibility:"hidden",marginTop:t.css("marginTop"),marginBottom:t.css("marginBottom"),marginLeft:t.css("marginLeft"),marginRight:t.css("marginRight"),float:t.css("float")}).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).addClass("ui-effects-placeholder"),t.data(j+"placeholder",e)),t.css({position:i,left:s.left,top:s.top}),e},removePlaceholder:function(t){var e=j+"placeholder",i=t.data(e);i&&(i.remove(),t.removeData(e))},cleanUp:function(t){V.effects.restoreStyle(t),V.effects.removePlaceholder(t)},setTransition:function(s,t,n,o){return o=o||{},V.each(t,function(t,e){var i=s.cssUnit(e);0");l.appendTo("body").addClass(t.className).css({top:s.top-a,left:s.left-r,height:i.innerHeight(),width:i.innerWidth(),position:n?"fixed":"absolute"}).animate(o,t.duration,t.easing,function(){l.remove(),"function"==typeof e&&e()})}}),V.fx.step.clip=function(t){t.clipInit||(t.start=V(t.elem).cssClip(),"string"==typeof t.end&&(t.end=G(t.end,t.elem)),t.clipInit=!0),V(t.elem).cssClip({top:t.pos*(t.end.top-t.start.top)+t.start.top,right:t.pos*(t.end.right-t.start.right)+t.start.right,bottom:t.pos*(t.end.bottom-t.start.bottom)+t.start.bottom,left:t.pos*(t.end.left-t.start.left)+t.start.left})},Y={},V.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,t){Y[t]=function(t){return Math.pow(t,e+2)}}),V.extend(Y,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;t<((e=Math.pow(2,--i))-1)/11;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),V.each(Y,function(t,e){V.easing["easeIn"+t]=e,V.easing["easeOut"+t]=function(t){return 1-e(1-t)},V.easing["easeInOut"+t]=function(t){return t<.5?e(2*t)/2:1-e(-2*t+2)/2}});y=V.effects,V.effects.define("blind","hide",function(t,e){var i={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},s=V(this),n=t.direction||"up",o=s.cssClip(),a={clip:V.extend({},o)},r=V.effects.createPlaceholder(s);a.clip[i[n][0]]=a.clip[i[n][1]],"show"===t.mode&&(s.cssClip(a.clip),r&&r.css(V.effects.clipToBox(a)),a.clip=o),r&&r.animate(V.effects.clipToBox(a),t.duration,t.easing),s.animate(a,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("bounce",function(t,e){var i,s,n=V(this),o=t.mode,a="hide"===o,r="show"===o,l=t.direction||"up",h=t.distance,c=t.times||5,o=2*c+(r||a?1:0),u=t.duration/o,d=t.easing,p="up"===l||"down"===l?"top":"left",f="up"===l||"left"===l,g=0,t=n.queue().length;for(V.effects.createPlaceholder(n),l=n.css(p),h=h||n["top"==p?"outerHeight":"outerWidth"]()/3,r&&((s={opacity:1})[p]=l,n.css("opacity",0).css(p,f?2*-h:2*h).animate(s,u,d)),a&&(h/=Math.pow(2,c-1)),(s={})[p]=l;g").css({position:"absolute",visibility:"visible",left:-s*p,top:-i*f}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:p,height:f,left:n+(u?a*p:0),top:o+(u?r*f:0),opacity:u?0:1}).animate({left:n+(u?0:a*p),top:o+(u?0:r*f),opacity:u?1:0},t.duration||500,t.easing,m)}),V.effects.define("fade","toggle",function(t,e){var i="show"===t.mode;V(this).css("opacity",i?0:1).animate({opacity:i?1:0},{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("fold","hide",function(e,t){var i=V(this),s=e.mode,n="show"===s,o="hide"===s,a=e.size||15,r=/([0-9]+)%/.exec(a),l=!!e.horizFirst?["right","bottom"]:["bottom","right"],h=e.duration/2,c=V.effects.createPlaceholder(i),u=i.cssClip(),d={clip:V.extend({},u)},p={clip:V.extend({},u)},f=[u[l[0]],u[l[1]]],s=i.queue().length;r&&(a=parseInt(r[1],10)/100*f[o?0:1]),d.clip[l[0]]=a,p.clip[l[0]]=a,p.clip[l[1]]=0,n&&(i.cssClip(p.clip),c&&c.css(V.effects.clipToBox(p)),p.clip=u),i.queue(function(t){c&&c.animate(V.effects.clipToBox(d),h,e.easing).animate(V.effects.clipToBox(p),h,e.easing),t()}).animate(d,h,e.easing).animate(p,h,e.easing).queue(t),V.effects.unshift(i,s,4)}),V.effects.define("highlight","show",function(t,e){var i=V(this),s={backgroundColor:i.css("backgroundColor")};"hide"===t.mode&&(s.opacity=0),V.effects.saveStyle(i),i.css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(s,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("size",function(s,e){var n,i=V(this),t=["fontSize"],o=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],a=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],r=s.mode,l="effect"!==r,h=s.scale||"both",c=s.origin||["middle","center"],u=i.css("position"),d=i.position(),p=V.effects.scaledDimensions(i),f=s.from||p,g=s.to||V.effects.scaledDimensions(i,0);V.effects.createPlaceholder(i),"show"===r&&(r=f,f=g,g=r),n={from:{y:f.height/p.height,x:f.width/p.width},to:{y:g.height/p.height,x:g.width/p.width}},"box"!==h&&"both"!==h||(n.from.y!==n.to.y&&(f=V.effects.setTransition(i,o,n.from.y,f),g=V.effects.setTransition(i,o,n.to.y,g)),n.from.x!==n.to.x&&(f=V.effects.setTransition(i,a,n.from.x,f),g=V.effects.setTransition(i,a,n.to.x,g))),"content"!==h&&"both"!==h||n.from.y!==n.to.y&&(f=V.effects.setTransition(i,t,n.from.y,f),g=V.effects.setTransition(i,t,n.to.y,g)),c&&(c=V.effects.getBaseline(c,p),f.top=(p.outerHeight-f.outerHeight)*c.y+d.top,f.left=(p.outerWidth-f.outerWidth)*c.x+d.left,g.top=(p.outerHeight-g.outerHeight)*c.y+d.top,g.left=(p.outerWidth-g.outerWidth)*c.x+d.left),delete f.outerHeight,delete f.outerWidth,i.css(f),"content"!==h&&"both"!==h||(o=o.concat(["marginTop","marginBottom"]).concat(t),a=a.concat(["marginLeft","marginRight"]),i.find("*[width]").each(function(){var t=V(this),e=V.effects.scaledDimensions(t),i={height:e.height*n.from.y,width:e.width*n.from.x,outerHeight:e.outerHeight*n.from.y,outerWidth:e.outerWidth*n.from.x},e={height:e.height*n.to.y,width:e.width*n.to.x,outerHeight:e.height*n.to.y,outerWidth:e.width*n.to.x};n.from.y!==n.to.y&&(i=V.effects.setTransition(t,o,n.from.y,i),e=V.effects.setTransition(t,o,n.to.y,e)),n.from.x!==n.to.x&&(i=V.effects.setTransition(t,a,n.from.x,i),e=V.effects.setTransition(t,a,n.to.x,e)),l&&V.effects.saveStyle(t),t.css(i),t.animate(e,s.duration,s.easing,function(){l&&V.effects.restoreStyle(t)})})),i.animate(g,{queue:!1,duration:s.duration,easing:s.easing,complete:function(){var t=i.offset();0===g.opacity&&i.css("opacity",f.opacity),l||(i.css("position","static"===u?"relative":u).offset(t),V.effects.saveStyle(i)),e()}})}),V.effects.define("scale",function(t,e){var i=V(this),s=t.mode,s=parseInt(t.percent,10)||(0===parseInt(t.percent,10)||"effect"!==s?0:100),s=V.extend(!0,{from:V.effects.scaledDimensions(i),to:V.effects.scaledDimensions(i,s,t.direction||"both"),origin:t.origin||["middle","center"]},t);t.fade&&(s.from.opacity=1,s.to.opacity=0),V.effects.effect.size.call(this,s,e)}),V.effects.define("puff","hide",function(t,e){t=V.extend(!0,{},t,{fade:!0,percent:parseInt(t.percent,10)||150});V.effects.effect.scale.call(this,t,e)}),V.effects.define("pulsate","show",function(t,e){var i=V(this),s=t.mode,n="show"===s,o=2*(t.times||5)+(n||"hide"===s?1:0),a=t.duration/o,r=0,l=1,s=i.queue().length;for(!n&&i.is(":visible")||(i.css("opacity",0).show(),r=1);l li > :first-child").add(t.find("> :not(li)").even())},heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=V(),this._addClass("ui-accordion","ui-widget ui-helper-reset"),this.element.attr("role","tablist"),t.collapsible||!1!==t.active&&null!=t.active||(t.active=0),this._processPanels(),t.active<0&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():V()}},_createIcons:function(){var t,e=this.options.icons;e&&(t=V(""),this._addClass(t,"ui-accordion-header-icon","ui-icon "+e.header),t.prependTo(this.headers),t=this.active.children(".ui-accordion-header-icon"),this._removeClass(t,e.header)._addClass(t,null,e.activeHeader)._addClass(this.headers,"ui-accordion-icons"))},_destroyIcons:function(){this._removeClass(this.headers,"ui-accordion-icons"),this.headers.children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeAttr("role"),this.headers.removeAttr("role aria-expanded aria-selected aria-controls tabIndex").removeUniqueId(),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role aria-hidden aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){"active"!==t?("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||!1!==this.options.active||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons())):this._activate(e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t),this._toggleClass(this.headers.add(this.headers.next()),null,"ui-state-disabled",!!t)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var e=V.ui.keyCode,i=this.headers.length,s=this.headers.index(t.target),n=!1;switch(t.keyCode){case e.RIGHT:case e.DOWN:n=this.headers[(s+1)%i];break;case e.LEFT:case e.UP:n=this.headers[(s-1+i)%i];break;case e.SPACE:case e.ENTER:this._eventHandler(t);break;case e.HOME:n=this.headers[0];break;case e.END:n=this.headers[i-1]}n&&(V(t.target).attr("tabIndex",-1),V(n).attr("tabIndex",0),V(n).trigger("focus"),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===V.ui.keyCode.UP&&t.ctrlKey&&V(t.currentTarget).prev().trigger("focus")},refresh:function(){var t=this.options;this._processPanels(),!1===t.active&&!0===t.collapsible||!this.headers.length?(t.active=!1,this.active=V()):!1===t.active?this._activate(0):this.active.length&&!V.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=V()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var t=this.headers,e=this.panels;"function"==typeof this.options.header?this.headers=this.options.header(this.element):this.headers=this.element.find(this.options.header),this._addClass(this.headers,"ui-accordion-header ui-accordion-header-collapsed","ui-state-default"),this.panels=this.headers.next().filter(":not(.ui-accordion-content-active)").hide(),this._addClass(this.panels,"ui-accordion-content","ui-helper-reset ui-widget-content"),e&&(this._off(t.not(this.headers)),this._off(e.not(this.panels)))},_refresh:function(){var i,t=this.options,e=t.heightStyle,s=this.element.parent();this.active=this._findActive(t.active),this._addClass(this.active,"ui-accordion-header-active","ui-state-active")._removeClass(this.active,"ui-accordion-header-collapsed"),this._addClass(this.active.next(),"ui-accordion-content-active"),this.active.next().show(),this.headers.attr("role","tab").each(function(){var t=V(this),e=t.uniqueId().attr("id"),i=t.next(),s=i.uniqueId().attr("id");t.attr("aria-controls",s),i.attr("aria-labelledby",e)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(t.event),"fill"===e?(i=s.height(),this.element.siblings(":visible").each(function(){var t=V(this),e=t.css("position");"absolute"!==e&&"fixed"!==e&&(i-=t.outerHeight(!0))}),this.headers.each(function(){i-=V(this).outerHeight(!0)}),this.headers.next().each(function(){V(this).height(Math.max(0,i-V(this).innerHeight()+V(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.headers.next().each(function(){var t=V(this).is(":visible");t||V(this).show(),i=Math.max(i,V(this).css("height","").height()),t||V(this).hide()}).height(i))},_activate:function(t){t=this._findActive(t)[0];t!==this.active[0]&&(t=t||this.active[0],this._eventHandler({target:t,currentTarget:t,preventDefault:V.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):V()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&V.each(t.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var e=this.options,i=this.active,s=V(t.currentTarget),n=s[0]===i[0],o=n&&e.collapsible,a=o?V():s.next(),r=i.next(),a={oldHeader:i,oldPanel:r,newHeader:o?V():s,newPanel:a};t.preventDefault(),n&&!e.collapsible||!1===this._trigger("beforeActivate",t,a)||(e.active=!o&&this.headers.index(s),this.active=n?V():s,this._toggle(a),this._removeClass(i,"ui-accordion-header-active","ui-state-active"),e.icons&&(i=i.children(".ui-accordion-header-icon"),this._removeClass(i,null,e.icons.activeHeader)._addClass(i,null,e.icons.header)),n||(this._removeClass(s,"ui-accordion-header-collapsed")._addClass(s,"ui-accordion-header-active","ui-state-active"),e.icons&&(n=s.children(".ui-accordion-header-icon"),this._removeClass(n,null,e.icons.header)._addClass(n,null,e.icons.activeHeader)),this._addClass(s.next(),"ui-accordion-content-active")))},_toggle:function(t){var e=t.newPanel,i=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=e,this.prevHide=i,this.options.animate?this._animate(e,i,t):(i.hide(),e.show(),this._toggleComplete(t)),i.attr({"aria-hidden":"true"}),i.prev().attr({"aria-selected":"false","aria-expanded":"false"}),e.length&&i.length?i.prev().attr({tabIndex:-1,"aria-expanded":"false"}):e.length&&this.headers.filter(function(){return 0===parseInt(V(this).attr("tabIndex"),10)}).attr("tabIndex",-1),e.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(t,i,e){var s,n,o,a=this,r=0,l=t.css("box-sizing"),h=t.length&&(!i.length||t.index()",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.lastMousePosition={x:null,y:null},this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault(),this._activateItem(t)},"click .ui-menu-item":function(t){var e=V(t.target),i=V(V.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&e.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),e.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&i.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":"_activateItem","mousemove .ui-menu-item":"_activateItem",mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this._menuItems().first();e||this.focus(t,i)},blur:function(t){this._delay(function(){V.contains(this.element[0],V.ui.safeActiveElement(this.document[0]))||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t,!0),this.mouseHandled=!1}})},_activateItem:function(t){var e,i;this.previousFilter||t.clientX===this.lastMousePosition.x&&t.clientY===this.lastMousePosition.y||(this.lastMousePosition={x:t.clientX,y:t.clientY},e=V(t.target).closest(".ui-menu-item"),i=V(t.currentTarget),e[0]===i[0]&&(i.is(".ui-state-active")||(this._removeClass(i.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(t,i))))},_destroy:function(){var t=this.element.find(".ui-menu-item").removeAttr("role aria-disabled").children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),t.children().each(function(){var t=V(this);t.data("ui-menu-submenu-caret")&&t.remove()})},_keydown:function(t){var e,i,s,n=!0;switch(t.keyCode){case V.ui.keyCode.PAGE_UP:this.previousPage(t);break;case V.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case V.ui.keyCode.HOME:this._move("first","first",t);break;case V.ui.keyCode.END:this._move("last","last",t);break;case V.ui.keyCode.UP:this.previous(t);break;case V.ui.keyCode.DOWN:this.next(t);break;case V.ui.keyCode.LEFT:this.collapse(t);break;case V.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case V.ui.keyCode.ENTER:case V.ui.keyCode.SPACE:this._activate(t);break;case V.ui.keyCode.ESCAPE:this.collapse(t);break;default:e=this.previousFilter||"",s=n=!1,i=96<=t.keyCode&&t.keyCode<=105?(t.keyCode-96).toString():String.fromCharCode(t.keyCode),clearTimeout(this.filterTimer),i===e?s=!0:i=e+i,e=this._filterMenuItems(i),(e=s&&-1!==e.index(this.active.next())?this.active.nextAll(".ui-menu-item"):e).length||(i=String.fromCharCode(t.keyCode),e=this._filterMenuItems(i)),e.length?(this.focus(t,e),this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}n&&t.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var t,e,s=this,n=this.options.icons.submenu,i=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),e=i.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=V(this),e=t.prev(),i=V("").data("ui-menu-submenu-caret",!0);s._addClass(i,"ui-menu-icon","ui-icon "+n),e.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",e.attr("id"))}),this._addClass(e,"ui-menu","ui-widget ui-widget-content ui-front"),(t=i.add(this.element).find(this.options.items)).not(".ui-menu-item").each(function(){var t=V(this);s._isDivider(t)&&s._addClass(t,"ui-menu-divider","ui-widget-content")}),i=(e=t.not(".ui-menu-item, .ui-menu-divider")).children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(e,"ui-menu-item")._addClass(i,"ui-menu-item-wrapper"),t.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!V.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){var i;"icons"===t&&(i=this.element.find(".ui-menu-icon"),this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",String(t)),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),i=this.active.children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",i.attr("id")),i=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),(i=e.children(".ui-menu")).length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(t){var e,i,s;this._hasScroll()&&(i=parseFloat(V.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(V.css(this.activeMenu[0],"paddingTop"))||0,e=t.offset().top-this.activeMenu.offset().top-i-s,i=this.activeMenu.scrollTop(),s=this.activeMenu.height(),t=t.outerHeight(),e<0?this.activeMenu.scrollTop(i+e):s",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,liveRegionTimer:null,_create:function(){var i,s,n,t=this.element[0].nodeName.toLowerCase(),e="textarea"===t,t="input"===t;this.isMultiLine=e||!t&&this._isContentEditable(this.element),this.valueMethod=this.element[e||t?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(t){if(this.element.prop("readOnly"))s=n=i=!0;else{s=n=i=!1;var e=V.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:i=!0,this._move("previousPage",t);break;case e.PAGE_DOWN:i=!0,this._move("nextPage",t);break;case e.UP:i=!0,this._keyEvent("previous",t);break;case e.DOWN:i=!0,this._keyEvent("next",t);break;case e.ENTER:this.menu.active&&(i=!0,t.preventDefault(),this.menu.select(t));break;case e.TAB:this.menu.active&&this.menu.select(t);break;case e.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(t),t.preventDefault());break;default:s=!0,this._searchTimeout(t)}}},keypress:function(t){if(i)return i=!1,void(this.isMultiLine&&!this.menu.element.is(":visible")||t.preventDefault());if(!s){var e=V.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:this._move("previousPage",t);break;case e.PAGE_DOWN:this._move("nextPage",t);break;case e.UP:this._keyEvent("previous",t);break;case e.DOWN:this._keyEvent("next",t)}}},input:function(t){if(n)return n=!1,void t.preventDefault();this._searchTimeout(t)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){clearTimeout(this.searching),this.close(t),this._change(t)}}),this._initSource(),this.menu=V("