Project

General

Profile

Feature #37623 » feature-37623.patch

Mizuki ISHIKAWA, 2022-09-02 06:01

View differences:

app/models/time_entry_query.rb
34 34
    QueryAssociationColumn.new(:issue, :status, :caption => :field_status, :sortable => "#{IssueStatus.table_name}.position"),
35 35
    QueryAssociationColumn.new(:issue, :category, :caption => :field_category, :sortable => "#{IssueCategory.table_name}.name"),
36 36
    QueryAssociationColumn.new(:issue, :fixed_version, :caption => :field_fixed_version, :sortable => Version.fields_for_order_statement),
37
    QueryAssociationColumn.new(:issue, :parent, :caption => :field_parent_issue, :sortable => ["#{Issue.table_name}.root_id", "#{Issue.table_name}.lft ASC"], :default_order => 'desc'),
37 38
    QueryColumn.new(:comments),
38 39
    QueryColumn.new(:hours, :sortable => "#{TimeEntry.table_name}.hours", :totalable => true),
39 40
  ]
......
71 72
      :type => :list,
72 73
      :name => l("label_attribute_of_issue", :name => l(:field_fixed_version)),
73 74
      :values => lambda {fixed_version_values})
75
    add_available_filter(
76
      "issue.parent_id",
77
      :type => :tree,
78
      :name => l("label_attribute_of_issue", :name => l(:field_parent_issue)))
74 79
    add_available_filter(
75 80
      "issue.category_id",
76 81
      :type => :list_optional,
......
200 205
    end
201 206
  end
202 207

  
208
  def sql_for_issue_parent_id_field(field, operator, value)
209
    case operator
210
    when "="
211
      # accepts a comma separated list of ids
212
      parent_ids = value.first.to_s.scan(/\d+/).map(&:to_i).uniq
213
      issue_ids = Issue.where(:parent_id => parent_ids).pluck(:id)
214
      if issue_ids.present?
215
        "#{TimeEntry.table_name}.issue_id IN (#{issue_ids.join(',')})"
216
      else
217
        "1=0"
218
      end
219
    when "~"
220
      root_id, lft, rgt = Issue.where(:id => value.first.to_i).pick(:root_id, :lft, :rgt)
221
      issue_ids = Issue.where("#{Issue.table_name}.root_id = ? AND #{Issue.table_name}.lft > ? AND #{Issue.table_name}.rgt < ?", root_id, lft, rgt).pluck(:id) if root_id && lft && rgt
222
      if issue_ids.present?
223
        "#{TimeEntry.table_name}.issue_id IN (#{issue_ids.join(',')})"
224
      else
225
        "1=0"
226
      end
227
    else
228
      sql_for_field("parent_id", operator, value, Issue.table_name, "parent_id")
229
    end
230
  end
231

  
203 232
  def sql_for_activity_id_field(field, operator, value)
204 233
    ids = value.map(&:to_i).join(',')
205 234
    table_name = Enumeration.table_name
test/functional/timelog_controller_test.rb
1374 1374
    assert_select 'td.issue-category', :text => 'Printing'
1375 1375
  end
1376 1376

  
1377
  def test_index_with_issue_parent_filter
1378
    issue1 = Issue.generate!(project_id: 'ecookbook', parent_id: 2)
1379
    entry1 = TimeEntry.generate!(issue: issue1, hours: 2.5)
1380
    issue2 = Issue.generate!(project_id: 'ecookbook', parent_id: 5)
1381
    entry2 = TimeEntry.generate!(issue: issue2, hours: 5.0)
1382

  
1383
    get :index, params: {
1384
      project_id: 'ecookbook',
1385
      f: ['issue.parent_id'],
1386
      op: {'issue.parent_id' => '='},
1387
      v: {'issue.parent_id' => ['2,5']}
1388
    }
1389
    assert_response :success
1390
    assert_equal [entry1.id, entry2.id].sort, css_select('input[name="ids[]"]').map {|e| e.attr(:value).to_i}.sort
1391
  end
1392

  
1393
  def test_index_with_issue_parent_column
1394
    issue = Issue.generate!(project_id: 'ecookbook', parent_id: 2)
1395
    entry = TimeEntry.generate!(issue: issue, hours: 2.5)
1396

  
1397
    get :index, params: {
1398
      project_id: 'ecookbook',
1399
      c: %w(project spent_on issue comments hours issue.parent)
1400
    }
1401

  
1402
    assert_response :success
1403
    assert_select 'td.issue-parent', text: "#{issue.parent.tracker} ##{issue.parent.id}: #{issue.parent.subject}"
1404
  end
1405

  
1406
  def test_index_with_issue_parent_sort
1407
    issue1 = Issue.generate!(project_id: 'ecookbook', parent_id: 2)
1408
    entry1 = TimeEntry.generate!(issue: issue1, hours: 2.5)
1409
    issue2 = Issue.generate!(project_id: 'ecookbook', parent_id: 5)
1410
    entry2 = TimeEntry.generate!(issue: issue2, hours: 5.0)
1411

  
1412
    get :index, :params => {
1413
      :c => ["hours", 'issue.parent'],
1414
      :sort => 'issue.parent'
1415
    }
1416
    assert_response :success
1417

  
1418
    # Make sure that values are properly sorted
1419
    values = css_select("td.issue-parent").map(&:text).reject(&:blank?)
1420
    assert_equal ["#{issue1.parent.tracker} ##{issue1.parent.id}: #{issue1.parent.subject}", "#{issue2.parent.tracker} ##{issue2.parent.id}: #{issue2.parent.subject}"].sort, values.sort
1421
  end
1422

  
1377 1423
  def test_index_with_issue_fixed_version_column
1378 1424
    issue = Issue.find(1)
1379 1425
    issue.fixed_version = Version.find(3)
test/unit/query_test.rb
504 504
    find_issues_with_query(query)
505 505
  end
506 506

  
507
  def test_time_entry_operator_is_on_issue_parent_id_should_accept_comma_separated_values
508
    issue1 = Issue.generate!(project_id: 'ecookbook', parent_id: 2)
509
    entry1 = TimeEntry.generate!(issue: issue1)
510
    issue2 = Issue.generate!(project_id: 'ecookbook', parent_id: 5)
511
    entry2 = TimeEntry.generate!(issue: issue2)
512

  
513
    query = TimeEntryQuery.new(:name => '_')
514
    query.add_filter("issue.parent_id", '=', ['2,5'])
515
    entries = TimeEntry.where(query.statement).to_a
516
    assert_equal 2, entries.size
517
    assert_equal [entry1.id, entry2.id].sort, entries.map(&:id).sort
518
  end
519

  
520
  def test_time_entry_contains_operator_is_on_issue_parent_id
521
    issue1 = Issue.generate!(project_id: 'ecookbook', parent_id: 2)
522
    entry1 = TimeEntry.generate!(issue: issue1)
523
    issue2 = Issue.generate!(project_id: 'ecookbook', parent_id: issue1.id)
524
    entry2 = TimeEntry.generate!(issue: issue2)
525

  
526
    query = TimeEntryQuery.new(:name => '_')
527
    query.add_filter("issue.parent_id", '~', ['2'])
528
    entries = TimeEntry.where(query.statement).to_a
529
    assert_equal 2, entries.size
530
    assert_equal [entry1.id, entry2.id].sort, entries.map(&:id).sort
531
  end
532

  
507 533
  def test_date_filter_should_not_accept_non_date_values
508 534
    query = IssueQuery.new(:name => '_')
509 535
    query.add_filter('created_on', '=', ['a'])
(1-1/5)