diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index a677b80a8..57a5b8faf 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -672,16 +672,35 @@ module ApplicationHelper
if collection.include?(User.current)
s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id)
end
- groups = +''
+
+ shortcut_users_html = +''
+ # This optgroup is displayed only when editing a single issue
+ if @issue.present?
+ users = [@issue.author, @issue.prior_assigned_to].uniq.compact
+ shortcut_users_html = users.map do |user|
+ collection.include?(user) ? content_tag('option', user.name, value: user.id) : nil
+ end.join
+ end
+
+ users_html = +''
+ groups_html = +''
collection.sort.each do |element|
if option_value_selected?(element, selected) || element.id.to_s == selected
selected_attribute = ' selected="selected"'
end
- (element.is_a?(Group) ? groups : s) <<
+ (element.is_a?(Group) ? groups_html : users_html) <<
%()
end
- unless groups.empty?
- s << %()
+ if shortcut_users_html.blank? && groups_html.blank?
+ s << users_html
+ else
+ [
+ [l(:label_author_and_prior_assignee), shortcut_users_html],
+ [l(:label_user_plural), users_html],
+ [l(:label_group_plural), groups_html]
+ ].each do |label, options_html|
+ s << %() if options_html.present?
+ end
end
s.html_safe
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 9b47ce7bd..8492f5a47 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -925,6 +925,28 @@ class Issue < ApplicationRecord
result
end
+ # Returns the assignee immediately prior to the current one from the issue history
+ def prior_assigned_to
+ prior_assigned_to_id =
+ journals.joins(:details)
+ .where(details: {prop_key: 'assigned_to_id'})
+ .where.not(details: {old_value: nil})
+ .order(id: :desc)
+ .pick(:old_value)
+
+ prior_assigned_to_id && Principal.find_by(id: prior_assigned_to_id)
+ end
+
+ # Returns the previous assignee from the issue history
+ def previous_assigned_to
+ journals.reverse_each do |j|
+ previous_assignee_change = j.detail_for_attribute 'assigned_to_id'
+ return User.find_by(id: previous_assignee_change.old_value.to_i) if previous_assignee_change && previous_assignee_change.old_value
+ end
+ nil
+ end
+
+
# Returns the initial status of the issue
# Returns nil for a new issue
def status_was
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 1584f5ef2..a20228b2f 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -909,6 +909,7 @@ en:
label_optional: optional
label_show_completed_versions: Show completed versions
label_me: me
+ label_previous_assignee: "Previous: %{name}"
label_board: Forum
label_board_new: New forum
label_board_plural: Forums
@@ -1145,6 +1146,7 @@ en:
label_default_query: Default query
label_edited: Edited
label_time_by_author: "%{time} by %{author}"
+ label_author_and_prior_assignee: Author / Prior assignee
button_login: Login
button_submit: Submit
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 8a6757757..bce1cade1 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -1445,3 +1445,5 @@ ja:
setting_issue_done_ratio_interval: 進捗率の選択肢の間隔
setting_copy_attachments_on_issue_copy: チケットをコピーするとき添付ファイルもコピー
field_thousands_delimiter: 3桁区切り表示
+ label_author_and_prior_assignee: 作成者・直前担当者
+
diff --git a/test/helpers/application_helper_test.rb b/test/helpers/application_helper_test.rb
index ab0d8f91f..e5c6ab3b3 100644
--- a/test/helpers/application_helper_test.rb
+++ b/test/helpers/application_helper_test.rb
@@ -2052,10 +2052,16 @@ class ApplicationHelperTest < Redmine::HelperTest
User.current = nil
set_language_if_valid 'en'
users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
- assert_equal(
- %() +
- %(),
- principals_options_for_select(users))
+ result = principals_options_for_select(users)
+
+ assert_select_in result, 'optgroup[label="Users"]' do
+ assert_select 'option[value="2"]', text: 'John Smith'
+ assert_select 'option[value="4"]', text: 'Robert Hill'
+ end
+ assert_select_in result, 'optgroup[label="Groups"]' do
+ assert_select 'option[value="10"]', text: 'A Team'
+ assert_select 'option[value="11"]', text: 'B Team'
+ end
end
def test_principals_options_for_select_with_empty_collection
@@ -2070,6 +2076,22 @@ class ApplicationHelperTest < Redmine::HelperTest
principals_options_for_select(users)
end
+ def test_principals_options_for_select_should_include_author_and_prior_assignee
+ set_language_if_valid 'en'
+ users = [User.find(2), User.find(3), User.find(1)]
+ @issue = Issue.generate!(author_id: 1, assigned_to_id: 2)
+ @issue.init_journal(users.first, 'update')
+ @issue.assigned_to_id = 3
+ @issue.save
+
+ result = principals_options_for_select(users)
+ assert_select_in result, 'optgroup[label="Author / Prior assignee"]' do
+ assert_select 'option:nth-of-type(1)', text: 'Redmine Admin' # Author
+ assert_select 'option:nth-of-type(2)', text: 'John Smith' # Prior assignee
+ end
+ end
+
+
def test_stylesheet_link_tag_should_pick_the_default_stylesheet
assert_match 'href="/assets/styles.css"', stylesheet_link_tag("styles")
end
diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb
index 7480fbc55..d5e2ab87d 100644
--- a/test/unit/issue_test.rb
+++ b/test/unit/issue_test.rb
@@ -3247,6 +3247,15 @@ class IssueTest < ActiveSupport::TestCase
assert_equal was_closed_on, issue.closed_on
end
+ def test_prior_assigned_to
+ issue = Issue.generate!(assigned_to_id: 2)
+ issue.init_journal(User.find(2), 'update')
+ issue.assigned_to_id = 3
+ issue.save
+
+ assert_equal User.find(2), issue.prior_assigned_to
+ end
+
def test_status_was_should_return_nil_for_new_issue
issue = Issue.new
assert_nil issue.status_was