Project

General

Profile

Patch #1667 » 1667-20231031.patch

Minoru Maeda, 2023-10-31 03:54

View differences:

app/helpers/projects_helper.rb
123 123
    grouped_options_for_select(grouped, project.default_issue_query_id)
124 124
  end
125 125

  
126
  def project_default_tracker_options(project, role = nil)
127
    trackers = project.trackers.to_a
128
    trackers = trackers.select { |t| role.permissions_tracker?(:add_issues, t) } if role
129

  
130
    selected = project.project_default_tracker(role)&.tracker_id
131
    options_for_select(trackers.map { |t| [t.name, t.id] }, selected)
132
  end
133

  
126 134
  def format_version_sharing(sharing)
127 135
    sharing = 'none' unless Version::VERSION_SHARINGS.include?(sharing)
128 136
    l("label_version_sharing_#{sharing}")
app/models/issue.rb
448 448
        self.fixed_version_id = project.default_version_id
449 449
      end
450 450
    end
451
    # Set tracker to the project default tracker with role
452
    if new_record? && tracker.nil? && project
453
      self.tracker_id = project.default_tracker&.id
454
    end
455

  
451 456
    self.project
452 457
  end
453 458

  
app/models/project.rb
41 41
  has_many :versions, :dependent => :destroy
42 42
  belongs_to :default_version, :class_name => 'Version'
43 43
  belongs_to :default_assigned_to, :class_name => 'Principal'
44
  has_many :project_default_trackers, :autosave => true
44 45
  has_many :time_entries, :dependent => :destroy
45 46
  # Specific overridden Activities
46 47
  has_many :time_entry_activities, :dependent => :destroy
......
835 836
    'parent_id',
836 837
    'default_version_id',
837 838
    'default_issue_query_id',
838
    'default_assigned_to_id')
839
    'default_assigned_to_id',
840
    'default_tracker_id_for_all_roles',
841
    'default_tracker_ids_by_role')
839 842

  
840 843
  safe_attributes(
841 844
    'is_public',
......
908 911
    super(attrs, user)
909 912
  end
910 913

  
914
  def default_tracker
915
    tracker_id = if self.has_default_tracker_for_all_roles?
916
                   self.project_default_tracker&.tracker_id
917
                 else
918
                   role_ids = User.current.roles_for_project(self).map(&:id)
919
                   role = Role.givable.sorted.where(id: role_ids).first
920

  
921
                   self.project_default_tracker(role)&.tracker_id
922
                 end
923

  
924
    self.trackers.find_by(id: tracker_id)
925
  end
926

  
927
  def project_default_tracker(role = nil)
928
    self.project_default_trackers.find_by(role_id: role&.id)
929
  end
930

  
931
  def has_default_tracker_for_all_roles?
932
    self.project_default_trackers.where.not(role_id: nil).empty?
933
  end
934

  
935
  def default_tracker_id_for_all_roles=(tracker_id)
936
    self.project_default_trackers.each(&:mark_for_destruction)
937
    self.project_default_trackers.build(role_id: nil, tracker_id: tracker_id)
938
  end
939

  
940
  def default_tracker_ids_by_role=(tracker_ids_by_role)
941
    self.project_default_trackers.each(&:mark_for_destruction)
942

  
943
    Role.givable.sorted.find_each do |role|
944
      tracker_id = tracker_ids_by_role[role.id.to_s]
945
      self.project_default_trackers.build(role_id: role.id, tracker_id: tracker_id)
946
    end
947
  end
948

  
911 949
  # Returns an auto-generated project identifier based on the last identifier used
912 950
  def self.next_identifier
913 951
    p = Project.order('id DESC').first
app/models/project_default_tracker.rb
1
# frozen_string_literal: true
2

  
3
# Redmine - project management software
4
# Copyright (C) 2006-2023  Jean-Philippe Lang
5
#
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; either version 2
9
# of the License, or (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19

  
20
class ProjectDefaultTracker < ActiveRecord::Base
21
  self.table_name = "#{table_name_prefix}project_default_trackers#{table_name_suffix}"
22

  
23
  belongs_to :tracker
24
end
app/views/projects/settings/_issues.html.erb
46 46
  <% if @project.safe_attribute?('default_issue_query_id') %>
47 47
    <p><%= f.select :default_issue_query_id, project_default_issue_query_options(@project), include_blank: l(:label_none) %><em class="info"><%=l 'text_allowed_queries_to_select' %></em></p>
48 48
  <% end %>
49

  
50
    <div style="padding-left: 180px;">
51
      <label><%= l(:label_default_tracker) %></label>
52
      <table style="display: inline-block;">
53
        <tr class="default_tracker_for_all_roles">
54
          <td>
55
            <label class="no-css">
56
              <%= radio_button_tag 'project[default_tracker_for_all_roles]', 1, @project.has_default_tracker_for_all_roles?,
57
                    data: { disables: '.default_tracker_by_role select', enables: '.default_tracker_for_all_roles select' } %>
58
              <%= l(:label_default_tracker_for_all_roles) %>
59
            </label>
60
          </td>
61
          <td>
62
            <%= select_tag 'project[default_tracker_id_for_all_roles]', project_default_tracker_options(@project), prompt: l(:label_none) %>
63
          </td>
64
        </tr>
65
        <tr>
66
          <td>
67
            <label class="no-css">
68
              <%= radio_button_tag 'project[default_tracker_for_all_roles]', 0, !@project.has_default_tracker_for_all_roles?,
69
                    data: { enables: '.default_tracker_by_role select', disables: '.default_tracker_for_all_roles select' } %>
70
              <%= l(:label_default_tracker_by_role) %>:
71
            </label>
72
          </td>
73
          <td></td>
74
        </tr>
75

  
76
        <% Role.givable.sorted.each do |role| %>
77
          <tr class="default_tracker_by_role">
78
            <td style="text-align: right;"><%= role.name %></td>
79
            <td>
80
              <%= select_tag "project[default_tracker_ids_by_role][#{role.id}]", project_default_tracker_options(@project, role), prompt: l(:label_none) %>
81
            </td>
82
          </tr>
83
        <% end %>
84
      </table>
85
    </div>
86

  
49 87
  </div>
50 88

  
51 89
  <p><%= submit_tag l(:button_save) %></p>
config/locales/en.yml
1412 1412
  text_user_destroy_confirmation: "Are you sure you want to delete this user and remove all references to them? This cannot be undone. Often, locking a user instead of deleting them is the better solution. To confirm, please enter their login (%{login}) below."
1413 1413
  text_project_destroy_enter_identifier: "To confirm, please enter the project's identifier (%{identifier}) below."
1414 1414
  field_name_or_email_or_login: Name, email or login
1415
  label_default_tracker: Default tracker
1416
  label_default_tracker_for_all_roles: For all roles
1417
  label_default_tracker_by_role: By role
config/locales/ja.yml
1438 1438
  text_select_apply_issue_status: このステータスを適用
1439 1439
  field_name_or_email_or_login: 姓名・メールアドレス・ログインID
1440 1440
  text_default_active_job_queue_changed: キューアダプターがデフォルト (開発・テスト用) 以外のものに変更済み
1441
  label_default_tracker: デフォルトのトラッカー
1442
  label_default_tracker_for_all_roles: すべてのロールで共通
1443
  label_default_tracker_by_role: ロールごとに設定する
db/migrate/20231031075958_create_project_default_trackers.rb
1
class CreateProjectDefaultTrackers < ActiveRecord::Migration[6.1]
2
  def change
3
    create_table :project_default_trackers do |t|
4
      t.integer :project_id, :null => false
5
      t.integer :role_id, :null => true
6
      t.integer :tracker_id, :null => true
7
    end
8

  
9
    add_index :project_default_trackers, [:project_id, :tracker_id, :role_id], :unique => true, :name => :project_default_trackers_role_id
10
  end
11
end
test/functional/issues_controller_test.rb
3529 3529
    end
3530 3530
  end
3531 3531

  
3532
  def test_new_should_preselect_default_tracker
3533
    ProjectDefaultTracker.create!(
3534
      :project_id => 1, :tracker_id => 3, :role_id => nil
3535
    )
3536
    assert_not_equal Project.find(1).trackers.first.id, 3
3537

  
3538
    @request.session[:user_id] = 2
3539
    get(:new, :params => {:project_id => 1})
3540
    assert_response :success
3541
    assert_select 'select[name=?]', 'issue[tracker_id]' do
3542
      assert_select 'option[value=?][selected=selected]', '3'
3543
    end
3544
  end
3545

  
3532 3546
  def test_get_new_with_list_custom_field
3533 3547
    @request.session[:user_id] = 2
3534 3548
    get(
test/functional/projects_controller_test.rb
1047 1047
    assert_select 'input[name=?]', 'project[issue_custom_field_ids][]'
1048 1048
    assert_select 'select[name=?]', 'project[default_version_id]', 1
1049 1049
    assert_select 'select[name=?]', 'project[default_assigned_to_id]', 1
1050
    assert_select 'select[name=?]', 'project[default_tracker_id_for_all_roles]', 1
1050 1051
  end
1051 1052

  
1052 1053
  def test_update
test/unit/issue_test.rb
651 651
    assert_equal version, issue.fixed_version
652 652
  end
653 653

  
654
  def test_setting_project_should_set_tracker_to_default_tracker_for_all_roles
655
    issue = Issue.new(:project_id => 1)
656
    assert_nil issue.tracker
657

  
658
    ProjectDefaultTracker.create!(
659
      :project_id => 1, :tracker_id => 3, :role_id => nil
660
    )
661

  
662
    issue = Issue.new(:project_id => 1)
663
    assert_equal 3, issue.tracker_id
664
    assert_not_equal Project.find(1).trackers.first, issue.tracker
665
  end
666

  
667
  def test_setting_project_should_set_tracker_to_default_tracker_by_role
668
    User.current = User.find_by_login('jsmith')
669
    issue = Issue.new(:project_id => 1)
670
    assert_nil issue.tracker_id
671

  
672
    ProjectDefaultTracker.create!(
673
      :project_id => 1, :tracker_id => 3, :role_id => 1
674
    )
675
    User.current = User.find_by_login('jsmith')
676

  
677
    issue = Issue.new(:project_id => 1)
678
    assert_equal 3, issue.tracker_id
679
    assert_equal 1, User.current.roles_for_project(Project.find(1)).first.id
680
  end
681

  
682
  def test_setting_project_should_not_set_a_disallowed_tracker
683
    disallowed_tracker = Tracker.generate!
684
    ProjectDefaultTracker.create!(
685
      :project_id => 1, :tracker_id => disallowed_tracker.id, :role_id => nil
686
    )
687

  
688
    issue = Issue.new(:project_id => 1)
689
    assert_nil issue.tracker_id
690
    assert_not_includes Project.find(1).trackers.pluck(:id), disallowed_tracker.id
691
  end
692

  
654 693
  def test_default_assigned_to_based_on_category_should_be_set_on_create
655 694
    user = User.find(3)
656 695
    category = IssueCategory.create!(:project_id => 1, :name => 'With default assignee', :assigned_to_id => 3)
(3-3/3)