Project

General

Profile

Feature #44253 » add-assignee-or-watcher-filter.patch

kyohei yamada, 2026-07-10 13:49

View differences:

app/models/issue_query.rb
254 254
        "watcher_id",
255 255
        :type => :list, :values => lambda {watcher_values}
256 256
      )
257
      add_available_filter(
258
        "assigned_to_or_watcher_id",
259
        :type => :list, :values => lambda {assigned_to_or_watcher_values}
260
      )
257 261
    end
258 262
    add_available_filter(
259 263
      "updated_by",
......
577 581
    "#{Issue.table_name}.id #{ operator == '=' ? 'IN' : 'NOT IN' } (#{sql})"
578 582
  end
579 583

  
584
  def assigned_to_or_watcher_values
585
    (assigned_to_values + watcher_values).uniq {|value| value[1]}
586
  end
587

  
588
  def sql_for_assigned_to_or_watcher_id_field(field, operator, value)
589
    assigned_to_sql =
590
      sql_for_field(
591
        "assigned_to_id", operator, value,
592
        Issue.table_name, "assigned_to_id", false
593
      )
594
    watcher_sql = sql_for_watcher_id_field("watcher_id", operator, value)
595
    conjunction = operator == '=' ? ' OR ' : ' AND '
596

  
597
    "(#{assigned_to_sql}#{conjunction}#{watcher_sql})"
598
  end
599

  
580 600
  def sql_for_member_of_group_field(field, operator, value)
581 601
    if operator == '*' # Any group
582 602
      groups = Group.givable
......
905 925
    Principal.visible.where(:id => values).map {|p| [p.name, p.id.to_s]}
906 926
  end
907 927
  alias :find_author_id_filter_values :find_assigned_to_id_filter_values
928
  alias :find_assigned_to_or_watcher_id_filter_values :find_assigned_to_id_filter_values
908 929

  
909 930
  IssueRelation::TYPES.each_key do |relation_type|
910 931
    alias_method :"sql_for_#{relation_type}_field", :sql_for_relations
app/models/query.rb
1006 1006
      operator = operator_for(field)
1007 1007

  
1008 1008
      # "me" value substitution
1009
      if %w(assigned_to_id author_id user_id watcher_id updated_by last_updated_by).include?(field)
1009
      if %w(assigned_to_id assigned_to_or_watcher_id author_id user_id watcher_id updated_by last_updated_by).include?(field)
1010 1010
        if v.delete("me")
1011 1011
          if User.current.logged?
1012 1012
            v.push(User.current.id.to_s)
1013
            v += User.current.group_ids.map(&:to_s) if %w(assigned_to_id watcher_id).include?(field)
1013
            v += User.current.group_ids.map(&:to_s) if %w(assigned_to_id assigned_to_or_watcher_id watcher_id).include?(field)
1014 1014
          else
1015 1015
            v.push("0")
1016 1016
          end
config/locales/en.yml
318 318
  field_subject: Subject
319 319
  field_due_date: Due date
320 320
  field_assigned_to: Assignee
321
  field_assigned_to_or_watcher: Assignee or watcher
321 322
  field_priority: Priority
322 323
  field_fixed_version: Target version
323 324
  field_user: User
config/locales/ja.yml
273 273
  field_subject: 題名
274 274
  field_due_date: 期日
275 275
  field_assigned_to: 担当者
276
  field_assigned_to_or_watcher: 担当者またはウォッチャー
276 277
  field_priority: 優先度
277 278
  field_fixed_version: 対象バージョン
278 279
  field_user: ユーザー
test/unit/query_test.rb
1425 1425
    assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id)
1426 1426
  end
1427 1427

  
1428
  def test_assigned_to_or_watcher_filter_should_be_available_only_for_logged_users
1429
    assert_not IssueQuery.new.available_filters.key?('assigned_to_or_watcher_id')
1430

  
1431
    User.current = User.find(2)
1432
    assert IssueQuery.new.available_filters.key?('assigned_to_or_watcher_id')
1433
  end
1434

  
1435
  def test_filter_assigned_or_watched_issues_by_me_should_include_user_groups
1436
    user = User.find(2)
1437
    group = Group.find(10)
1438
    group.users << user
1439
    Member.create!(:project_id => 1, :principal => group, :role_ids => [1])
1440
    User.current = user
1441

  
1442
    manager = Role.find(1)
1443
    manager.remove_permission! :view_issue_watchers
1444

  
1445
    with_settings :issue_group_assignment => '1' do
1446
      assigned_to_user = Issue.generate!(:project_id => 1, :assigned_to => user)
1447
      assigned_to_group = Issue.generate!(:project_id => 1, :assigned_to => group)
1448
      watched_by_user = Issue.generate!(:project_id => 1)
1449
      watched_by_user.add_watcher(user)
1450
      watched_by_group = Issue.generate!(:project_id => 1)
1451
      watched_by_group.add_watcher(group)
1452
      assigned_and_watched = Issue.generate!(:project_id => 1, :assigned_to => user)
1453
      assigned_and_watched.add_watcher(user)
1454
      unrelated = Issue.generate!(:project_id => 1, :assigned_to => User.find(3))
1455

  
1456
      query =
1457
        IssueQuery.new(
1458
          :name => '_',
1459
          :filters => {
1460
            'assigned_to_or_watcher_id' => {
1461
              :operator => '=',
1462
              :values => ['me']
1463
            }
1464
          }
1465
        )
1466
      result = find_issues_with_query(query)
1467

  
1468
      assert_includes result, assigned_to_user
1469
      assert_includes result, assigned_to_group
1470
      assert_includes result, watched_by_user
1471
      assert_includes result, watched_by_group
1472
      assert_includes result, assigned_and_watched
1473
      assert_equal 1, result.count {|issue| issue == assigned_and_watched}
1474
      assert_not_includes result, unrelated
1475

  
1476
      query.filters = {
1477
        'assigned_to_or_watcher_id' => {
1478
          :operator => '!',
1479
          :values => ['me']
1480
        }
1481
      }
1482
      result = find_issues_with_query(query)
1483

  
1484
      assert_not_includes result, assigned_to_user
1485
      assert_not_includes result, assigned_to_group
1486
      assert_not_includes result, watched_by_user
1487
      assert_not_includes result, watched_by_group
1488
      assert_not_includes result, assigned_and_watched
1489
      assert_includes result, unrelated
1490
    end
1491
  end
1492

  
1493
  def test_filter_assigned_or_watched_issues_by_other_user_should_honor_watcher_visibility
1494
    user = User.find(2)
1495
    other_user = User.find(3)
1496
    User.current = user
1497

  
1498
    manager = Role.find(1)
1499
    manager.remove_permission! :view_issue_watchers
1500

  
1501
    assigned_to_other_user = Issue.generate!(:project_id => 1, :assigned_to => other_user)
1502
    watched_by_other_user = Issue.generate!(:project_id => 1)
1503
    watched_by_other_user.add_watcher(other_user)
1504

  
1505
    query =
1506
      IssueQuery.new(
1507
        :name => '_',
1508
        :filters => {
1509
          'assigned_to_or_watcher_id' => {
1510
            :operator => '=',
1511
            :values => [other_user.id.to_s]
1512
          }
1513
        }
1514
      )
1515
    result = find_issues_with_query(query)
1516

  
1517
    assert_includes result, assigned_to_other_user
1518
    assert_not_includes result, watched_by_other_user
1519
  end
1520

  
1428 1521
  def test_filter_watched_issues_by_me_should_include_user_groups
1429 1522
    user = User.find(2)
1430 1523
    group = Group.find(10)
    (1-1/1)