diff options
author | Go MAEDA <maeda@farend.jp> | 2023-05-11 02:08:41 +0000 |
---|---|---|
committer | Go MAEDA <maeda@farend.jp> | 2023-05-11 02:08:41 +0000 |
commit | 2caf5eaf973f82d3a9177f63378a642aec8b7d3b (patch) | |
tree | fce2bf5a112d3850ad4b6145aa02ae435431823e /app | |
parent | 8e170b1ec2f29666aea0166c9bad5575cf5eacce (diff) | |
download | redmine-2caf5eaf973f82d3a9177f63378a642aec8b7d3b.tar.gz redmine-2caf5eaf973f82d3a9177f63378a642aec8b7d3b.zip |
New issues filter operators "has been", "has never been", and "changed from" (#38527).
Patch by Go MAEDA.
git-svn-id: https://svn.redmine.org/redmine/trunk@22240 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r-- | app/models/issue_query.rb | 10 | ||||
-rw-r--r-- | app/models/query.rb | 30 |
2 files changed, 34 insertions, 6 deletions
diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb index e573f8782..a0420c994 100644 --- a/app/models/issue_query.rb +++ b/app/models/issue_query.rb @@ -155,11 +155,11 @@ class IssueQuery < Query ) if project.nil? add_available_filter( "tracker_id", - :type => :list, :values => trackers.collect{|s| [s.name, s.id.to_s]} + :type => :list_with_history, :values => trackers.collect{|s| [s.name, s.id.to_s]} ) add_available_filter( "priority_id", - :type => :list, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s]} + :type => :list_with_history, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s]} ) add_available_filter( "author_id", @@ -167,7 +167,7 @@ class IssueQuery < Query ) add_available_filter( "assigned_to_id", - :type => :list_optional, :values => lambda {assigned_to_values} + :type => :list_optional_with_history, :values => lambda {assigned_to_values} ) add_available_filter( "member_of_group", @@ -179,7 +179,7 @@ class IssueQuery < Query ) add_available_filter( "fixed_version_id", - :type => :list_optional, :values => lambda {fixed_version_values} + :type => :list_optional_with_history, :values => lambda {fixed_version_values} ) add_available_filter( "fixed_version.due_date", @@ -194,7 +194,7 @@ class IssueQuery < Query ) add_available_filter( "category_id", - :type => :list_optional, + :type => :list_optional_with_history, :values => lambda {project.issue_categories.collect{|s| [s.name, s.id.to_s]}} ) if project add_available_filter "subject", :type => :text diff --git a/app/models/query.rb b/app/models/query.rb index 00d99c24f..f4bbfb5cd 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -314,13 +314,18 @@ class Query < ActiveRecord::Base "!p" => :label_no_issues_in_project, "*o" => :label_any_open_issues, "!o" => :label_no_open_issues, + "ev" => :label_has_been, # "ev" stands for "ever" + "!ev" => :label_has_never_been, + "cf" => :label_changed_from } class_attribute :operators_by_filter_type self.operators_by_filter_type = { :list => [ "=", "!" ], - :list_status => [ "o", "=", "!", "c", "*" ], + :list_with_history => [ "=", "!", "ev", "!ev", "cf" ], + :list_status => [ "o", "=", "!", "ev", "!ev", "cf", "c", "*" ], :list_optional => [ "=", "!", "!*", "*" ], + :list_optional_with_history => [ "=", "!", "ev", "!ev", "cf", "!*", "*" ], :list_subprojects => [ "*", "!*", "=", "!" ], :date => [ "=", ">=", "<=", "><", "<t+", ">t+", "><t+", "t+", "nd", "t", "ld", "nw", "w", "lw", "l2w", "nm", "m", "lm", "y", ">t-", "<t-", "><t-", "t-", "!*", "*" ], :date_past => [ "=", ">=", "<=", "><", ">t-", "<t-", "><t-", "t-", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", "!*", "*" ], @@ -1438,6 +1443,29 @@ class Query < ActiveRecord::Base sql = sql_contains("#{db_table}.#{db_field}", value.first, :starts_with => true) when "$" sql = sql_contains("#{db_table}.#{db_field}", value.first, :ends_with => true) + when "ev", "!ev", "cf" + # has been, has never been, changed from + if queried_class == Issue && value.present? + neg = (operator.start_with?('!') ? 'NOT' : '') + subquery = + "SELECT 1 FROM #{Journal.table_name}" + + " INNER JOIN #{JournalDetail.table_name} ON #{Journal.table_name}.id = #{JournalDetail.table_name}.journal_id" + + " WHERE (#{Journal.visible_notes_condition(User.current, :skip_pre_condition => true)}" + + " AND #{Journal.table_name}.journalized_type = 'Issue'" + + " AND #{Journal.table_name}.journalized_id = #{db_table}.id" + + " AND #{JournalDetail.table_name}.property = 'attr'" + + " AND #{JournalDetail.table_name}.prop_key = '#{db_field}'" + + " AND " + + queried_class.send(:sanitize_sql_for_conditions, ["#{JournalDetail.table_name}.old_value IN (?)", value]) + + ")" + if %w[ev !ev].include?(operator) + subquery << + " OR " + queried_class.send(:sanitize_sql_for_conditions, ["#{db_table}.#{db_field} IN (?)", value]) + end + sql = "#{neg} EXISTS (#{subquery})" + else + sql = '1=0' + end else raise QueryError, "Unknown query operator #{operator}" end |