Feature #37623 » feature-37623.patch
| 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'])
|