diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb index 137764e..7e94675 100644 --- a/app/models/issue_query.rb +++ b/app/models/issue_query.rb @@ -124,12 +124,12 @@ class IssueQuery < Query add_available_filter "priority_id", :type => :list, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s] } - author_values = [] - author_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? - author_values += users.collect{|s| [s.name, s.id.to_s] } + user_values = [] + user_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? + user_values += users.collect{|s| [s.name, s.id.to_s] } add_available_filter("author_id", - :type => :list, :values => author_values - ) unless author_values.empty? + :type => :list, :values => user_values + ) unless user_values.empty? assigned_to_values = [] assigned_to_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged? @@ -194,6 +194,16 @@ class IssueQuery < Query :values => subprojects.collect{|s| [s.name, s.id.to_s] } end + unless user_values.empty? + add_available_filter("updated_by", + :type => :list, :values => user_values + ) + + add_available_filter("last_updated_by", + :type => :list, :values => user_values + ) + end + add_custom_fields_filters(issue_custom_fields) add_associations_custom_fields_filters :project, :author, :assigned_to, :fixed_version @@ -504,6 +514,20 @@ class IssueQuery < Query end end + def sql_for_updated_by_field(field, operator, value) + db_table = Journal.table_name + + "#{Issue.table_name}.id IN (SELECT #{db_table}.journalized_id FROM #{db_table} WHERE #{db_table}.journalized_type='Issue' AND #{db_table}.journalized_id = #{Issue.table_name}.id AND " + + sql_for_field(field, operator, value, db_table, 'user_id') + ')' + end + + def sql_for_last_updated_by_field(field, operator, value) + db_table = Journal.table_name + + "#{Issue.table_name}.id IN (SELECT max(#{db_table}.journalized_id) FROM #{db_table} WHERE #{db_table}.journalized_type='Issue' AND #{db_table}.created_on = #{Issue.table_name}.updated_on AND #{db_table}.journalized_id = #{Issue.table_name}.id AND " + + sql_for_field(field, operator, value, db_table, 'user_id') + ')' + end + def sql_for_relations(field, operator, value, options={}) relation_options = IssueRelation::TYPES[field] return relation_options unless relation_options diff --git a/app/models/query.rb b/app/models/query.rb index ef2efc7..f7cd986 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -695,7 +695,7 @@ class Query < ActiveRecord::Base operator = operator_for(field) # "me" value substitution - if %w(assigned_to_id author_id user_id watcher_id).include?(field) + if %w(assigned_to_id author_id user_id watcher_id updated_by last_updated_by).include?(field) if v.delete("me") if User.current.logged? v.push(User.current.id.to_s) diff --git a/config/locales/en.yml b/config/locales/en.yml index 56a06c7..455e1cf 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -365,6 +365,8 @@ en: field_default_version: Default version field_remote_ip: IP address field_textarea_font: Font used for text areas + field_updated_by: Updated by + field_last_updated_by: Last updated by setting_app_title: Application title setting_app_subtitle: Application subtitle diff --git a/test/fixtures/issues.yml b/test/fixtures/issues.yml index fb2216b..b73adf5 100644 --- a/test/fixtures/issues.yml +++ b/test/fixtures/issues.yml @@ -1,16 +1,16 @@ ---- -issues_001: +--- +issues_001: created_on: <%= 3.days.ago.to_s(:db) %> project_id: 1 - updated_on: <%= 1.day.ago.to_s(:db) %> + updated_on: <%= 1.days.ago.to_date.to_s(:db) %> priority_id: 4 subject: Cannot print recipes id: 1 - fixed_version_id: + fixed_version_id: category_id: 1 description: Unable to print recipes tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 2 status_id: 1 start_date: <%= 1.day.ago.to_date.to_s(:db) %> @@ -19,7 +19,7 @@ issues_001: lft: 1 rgt: 2 lock_version: 3 -issues_002: +issues_002: created_on: 2006-07-19 21:04:21 +02:00 project_id: 1 updated_on: 2006-07-19 21:09:50 +02:00 @@ -27,28 +27,28 @@ issues_002: subject: Add ingredients categories id: 2 fixed_version_id: 2 - category_id: + category_id: description: Ingredients of the recipe should be classified by categories tracker_id: 2 assigned_to_id: 3 author_id: 2 status_id: 2 start_date: <%= 2.day.ago.to_date.to_s(:db) %> - due_date: + due_date: root_id: 2 lft: 1 rgt: 2 lock_version: 3 done_ratio: 30 -issues_003: +issues_003: created_on: 2006-07-19 21:07:27 +02:00 project_id: 1 updated_on: 2006-07-19 21:07:27 +02:00 priority_id: 4 subject: Error 281 when updating a recipe id: 3 - fixed_version_id: - category_id: + fixed_version_id: + category_id: description: Error 281 is encountered when saving a recipe tracker_id: 1 assigned_to_id: 3 @@ -59,15 +59,15 @@ issues_003: root_id: 3 lft: 1 rgt: 2 -issues_004: +issues_004: created_on: <%= 5.days.ago.to_s(:db) %> project_id: 2 updated_on: <%= 2.days.ago.to_s(:db) %> priority_id: 4 subject: Issue on project 2 id: 4 - fixed_version_id: - category_id: + fixed_version_id: + category_id: description: Issue on project 2 tracker_id: 1 assigned_to_id: 2 @@ -76,35 +76,35 @@ issues_004: root_id: 4 lft: 1 rgt: 2 -issues_005: +issues_005: created_on: <%= 5.days.ago.to_s(:db) %> project_id: 3 updated_on: <%= 2.days.ago.to_s(:db) %> priority_id: 4 subject: Subproject issue id: 5 - fixed_version_id: - category_id: + fixed_version_id: + category_id: description: This is an issue on a cookbook subproject tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 2 status_id: 1 root_id: 5 lft: 1 rgt: 2 -issues_006: +issues_006: created_on: <%= 1.minute.ago.to_s(:db) %> project_id: 5 - updated_on: <%= 1.minute.ago.to_s(:db) %> + updated_on: <%= 1.days.ago.to_date.to_s(:db) %> priority_id: 4 subject: Issue of a private subproject id: 6 - fixed_version_id: - category_id: + fixed_version_id: + category_id: description: This is an issue of a private subproject of cookbook tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 2 status_id: 1 start_date: <%= Date.today.to_s(:db) %> @@ -112,18 +112,18 @@ issues_006: root_id: 6 lft: 1 rgt: 2 -issues_007: +issues_007: created_on: <%= 10.days.ago.to_s(:db) %> project_id: 1 updated_on: <%= 10.days.ago.to_s(:db) %> priority_id: 5 subject: Issue due today id: 7 - fixed_version_id: - category_id: + fixed_version_id: + category_id: description: This is an issue that is due today tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 2 status_id: 1 start_date: <%= 10.days.ago.to_s(:db) %> @@ -132,39 +132,39 @@ issues_007: root_id: 7 lft: 1 rgt: 2 -issues_008: +issues_008: created_on: <%= 10.days.ago.to_s(:db) %> project_id: 1 updated_on: <%= 10.days.ago.to_s(:db) %> priority_id: 5 subject: Closed issue id: 8 - fixed_version_id: - category_id: + fixed_version_id: + category_id: description: This is a closed issue. tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 2 status_id: 5 - start_date: - due_date: + start_date: + due_date: lock_version: 0 root_id: 8 lft: 1 rgt: 2 closed_on: <%= 3.days.ago.to_s(:db) %> -issues_009: +issues_009: created_on: <%= 1.minute.ago.to_s(:db) %> project_id: 5 updated_on: <%= 1.minute.ago.to_s(:db) %> priority_id: 5 subject: Blocked Issue id: 9 - fixed_version_id: - category_id: + fixed_version_id: + category_id: description: This is an issue that is blocked by issue #10 tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 2 status_id: 1 start_date: <%= Date.today.to_s(:db) %> @@ -172,18 +172,18 @@ issues_009: root_id: 9 lft: 1 rgt: 2 -issues_010: +issues_010: created_on: <%= 1.minute.ago.to_s(:db) %> project_id: 5 updated_on: <%= 1.minute.ago.to_s(:db) %> priority_id: 5 subject: Issue Doing the Blocking id: 10 - fixed_version_id: - category_id: + fixed_version_id: + category_id: description: This is an issue that blocks issue #9 tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 2 status_id: 1 start_date: <%= Date.today.to_s(:db) %> @@ -191,18 +191,18 @@ issues_010: root_id: 10 lft: 1 rgt: 2 -issues_011: +issues_011: created_on: <%= 3.days.ago.to_s(:db) %> project_id: 1 updated_on: <%= 1.day.ago.to_s(:db) %> priority_id: 5 subject: Closed issue on a closed version id: 11 - fixed_version_id: 1 + fixed_version_id: 1 category_id: 1 description: tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 2 status_id: 5 start_date: <%= 1.day.ago.to_date.to_s(:db) %> @@ -211,18 +211,18 @@ issues_011: lft: 1 rgt: 2 closed_on: <%= 1.day.ago.to_s(:db) %> -issues_012: +issues_012: created_on: <%= 3.days.ago.to_s(:db) %> project_id: 1 updated_on: <%= 1.day.ago.to_s(:db) %> priority_id: 5 subject: Closed issue on a locked version id: 12 - fixed_version_id: 2 + fixed_version_id: 2 category_id: 1 description: tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 3 status_id: 5 start_date: <%= 1.day.ago.to_date.to_s(:db) %> @@ -238,11 +238,11 @@ issues_013: priority_id: 4 subject: Subproject issue two id: 13 - fixed_version_id: - category_id: + fixed_version_id: + category_id: description: This is a second issue on a cookbook subproject tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 2 status_id: 1 root_id: 13 @@ -252,14 +252,14 @@ issues_014: id: 14 created_on: <%= 15.days.ago.to_s(:db) %> project_id: 3 - updated_on: <%= 15.days.ago.to_s(:db) %> + updated_on: <%= 15.days.ago.to_date.to_s(:db) %> priority_id: 5 subject: Private issue on public project - fixed_version_id: - category_id: + fixed_version_id: + category_id: description: This is a private issue tracker_id: 1 - assigned_to_id: + assigned_to_id: author_id: 2 status_id: 1 is_private: true diff --git a/test/fixtures/journals.yml b/test/fixtures/journals.yml index 2156b78..6f445be 100644 --- a/test/fixtures/journals.yml +++ b/test/fixtures/journals.yml @@ -1,4 +1,4 @@ ---- +--- journals_001: created_on: <%= 2.days.ago.to_date.to_s(:db) %> notes: "Journal notes" @@ -6,7 +6,7 @@ journals_001: journalized_type: Issue user_id: 1 journalized_id: 1 -journals_002: +journals_002: created_on: <%= 1.days.ago.to_date.to_s(:db) %> notes: "Some notes with Redmine links: #2, r2." id: 2 @@ -14,7 +14,7 @@ journals_002: user_id: 2 journalized_id: 1 journals_003: - created_on: <%= 1.days.ago.to_date.to_s(:db) %> + created_on: 2006-07-19 21:09:50 +02:00 notes: "A comment with inline image: !picture.jpg! and a reference to #1 and r2." id: 3 journalized_type: Issue @@ -29,8 +29,15 @@ journals_004: journalized_id: 6 journals_005: id: 5 - created_on: <%= 1.days.ago.to_date.to_s(:db) %> + created_on: <%= 15.days.ago.to_date.to_s(:db) %> notes: "A comment on a private issue." user_id: 2 journalized_type: Issue journalized_id: 14 +journals_006: + id: 6 + created_on: 2006-07-19 21:07:27 +02:00 + notes: "New updates" + user_id: 3 + journalized_type: Issue + journalized_id: 3 \ No newline at end of file diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index fe056a7..43d0903 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -2702,7 +2702,7 @@ class IssueTest < ActiveSupport::TestCase end def test_last_journal_id_without_journals_should_return_nil - assert_nil Issue.find(3).last_journal_id + assert_nil Issue.find(4).last_journal_id end def test_journals_after_should_return_journals_with_greater_id diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index 5c34d58..f3203ee 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -691,6 +691,40 @@ class QueryTest < ActiveSupport::TestCase assert !result.include?(i3) end + def test_filter_updated_by + query = IssueQuery.new(:name => '_') + filter_name = "updated_by" + assert_include filter_name, query.available_filters.keys + + query.filters = {filter_name => {:operator => '=', :values => [2]}} + assert_equal [1,2,14], find_issues_with_query(query).map(&:id).uniq.sort + + query.filters = {filter_name => {:operator => '=', :values => [4]}} + assert_equal [], find_issues_with_query(query).map(&:id).uniq.sort + + query.filters = {filter_name => {:operator => '!', :values => [3]}, 'project_id' => {:operator => '=', :values =>[3]}} + assert_equal [14], find_issues_with_query(query).map(&:id).uniq.sort + end + + def test_filter_updated_by_me + User.current = User.find(1) + + query = IssueQuery.new(:name => '_', :filters => { "updated_by" => {:operator => '=', :values => ['me']}}) + assert_equal [1,6], find_issues_with_query(query).map(&:id).uniq.sort + end + + def test_filter_last_updated_by + query = IssueQuery.new(:name => '_') + filter_name = "last_updated_by" + assert_include filter_name, query.available_filters.keys + + query.filters = {filter_name => {:operator => '=', :values => [2]}} + assert_equal [1,2,14], find_issues_with_query(query).map(&:id).uniq.sort + + query.filters = {filter_name => {:operator => '!', :values => [1,2]}} + assert_equal [3], find_issues_with_query(query).map(&:id).uniq.sort + end + def test_user_custom_field_filtered_on_me User.current = User.find(2) cf = IssueCustomField.create!(:field_format => 'user', :is_for_all => true, :is_filter => true, :name => 'User custom field', :tracker_ids => [1])