]> source.dussan.org Git - redmine.git/commitdiff
Add "Author / Previous assignee" group to assignee dropdown in issue form (#16045).
authorGo MAEDA <maeda@farend.jp>
Sun, 15 Sep 2024 06:31:30 +0000 (06:31 +0000)
committerGo MAEDA <maeda@farend.jp>
Sun, 15 Sep 2024 06:31:30 +0000 (06:31 +0000)
Patch by Luka Lüdicke (user:dkd-luedicke), Mizuki ISHIKAWA (user:ishikawa999), and Go MAEDA (user:maeda).

git-svn-id: https://svn.redmine.org/redmine/trunk@23059 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/helpers/application_helper.rb
app/models/issue.rb
config/locales/en.yml
config/locales/ja.yml
test/helpers/application_helper_test.rb
test/unit/issue_test.rb

index 8960f5ab9f17843012124736e7cea8b959f4dc41..7e13c995ca1d2f07f77023c774e5fc2054c00802 100644 (file)
@@ -672,16 +672,35 @@ module ApplicationHelper
     if collection.include?(User.current)
       s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id)
     end
-    groups = +''
+
+    involved_principals_html = +''
+    # This optgroup is displayed only when editing a single issue
+    if @issue.present? && !@issue.new_record?
+      involved_principals = [@issue.author, @issue.prior_assigned_to].uniq.compact
+      involved_principals_html = involved_principals.map do |p|
+        content_tag('option', p.name, value: p.id, disabled: !collection.include?(p))
+      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) <<
         %(<option value="#{element.id}"#{selected_attribute}>#{h element.name}</option>)
     end
-    unless groups.empty?
-      s << %(<optgroup label="#{h(l(:label_group_plural))}">#{groups}</optgroup>)
+    if involved_principals_html.blank? && groups_html.blank?
+      s << users_html
+    else
+      [
+        [l(:label_involved_principals), involved_principals_html],
+        [l(:label_user_plural), users_html],
+        [l(:label_group_plural), groups_html]
+      ].each do |label, options_html|
+        s << %(<optgroup label="#{h(label)}">#{options_html}</optgroup>) if options_html.present?
+      end
     end
     s.html_safe
   end
index 3debf90ec4ae4c0db6354909ddb4f5f1eb1c68e7..48a9355584a144a09b253fe7e5c39bb8df8224b3 100644 (file)
@@ -925,6 +925,18 @@ 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 initial status of the issue
   # Returns nil for a new issue
   def status_was
index 1584f5ef2e1ac3cb5cf47285c7a388825766cbfd..657297619eda3a28855e567c3fa2cf5b34d6b3e1 100644 (file)
@@ -1145,6 +1145,7 @@ en:
   label_default_query: Default query
   label_edited: Edited
   label_time_by_author: "%{time} by %{author}"
+  label_involved_principals: Author / Previous assignee
 
   button_login: Login
   button_submit: Submit
index 8a6757757691411236a3c15201dd0a753d824643..1faae3deb1f6187eda877267dec9fd30b8158da5 100644 (file)
@@ -1445,3 +1445,4 @@ ja:
   setting_issue_done_ratio_interval: 進捗率の選択肢の間隔
   setting_copy_attachments_on_issue_copy: チケットをコピーするとき添付ファイルもコピー
   field_thousands_delimiter: 3桁区切り表示
+  label_involved_principals: 作成者 / 直前担当者
index 6a7ba4b3066ff21b50c221c4265aabfd9b0d499b..76b39545ce0758392bf22a520136048140cd6e15 100644 (file)
@@ -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(
-      %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
-      %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
-      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,21 @@ class ApplicationHelperTest < Redmine::HelperTest
                    principals_options_for_select(users)
   end
 
+  def test_principals_options_for_select_should_include_author_and_previous_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 / Previous 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
index ca2531e58896f242c83ea1c3a8e5ab89a949ae6a..d9933128af64ec7955e032a8ede3e66119d7943c 100644 (file)
@@ -3257,6 +3257,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