Project

General

Profile

Feature #16621 » filter-relations-d4e1f70-r14601.patch

Arthur Andersen, 2015-09-16 17:49

View differences:

app/models/issue_query.rb
529 529
        op = (operator == "!p" ? 'NOT IN' : 'IN')
530 530
        comp = (operator == "=!p" ? '<>' : '=')
531 531
        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{self.class.connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{comp} #{value.first.to_i})"
532
      when "!|c", "*&o"
533
        op = (operator == "!|c" ? 'NOT IN' : 'IN')
534
        "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{self.class.connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{self.class.connection.quoted_false}))"
532 535
      end
533 536

  
534 537
    if relation_options[:sym] == field && !options[:reverse]
app/models/query.rb
201 201
    "!~"  => :label_not_contains,
202 202
    "=p"  => :label_any_issues_in_project,
203 203
    "=!p" => :label_any_issues_not_in_project,
204
    "!p"  => :label_no_issues_in_project
204
    "!p"  => :label_no_issues_in_project,
205
    "*&o" => :label_any_open_issues,
206
    "!|c" => :label_none_or_closed_issues
205 207
  }
206 208

  
207 209
  class_attribute :operators_by_filter_type
......
216 218
    :text => [  "~", "!~", "!*", "*" ],
217 219
    :integer => [ "=", ">=", "<=", "><", "!*", "*" ],
218 220
    :float => [ "=", ">=", "<=", "><", "!*", "*" ],
219
    :relation => ["=", "=p", "=!p", "!p", "!*", "*"],
221
    :relation => ["=", "=p", "=!p", "!p", "*&o", "!|c", "!*", "*"],
220 222
    :tree => ["=", "~", "!*", "*"]
221 223
  }
222 224

  
......
278 280
          # filter requires one or more values
279 281
          (values_for(field) and !values_for(field).first.blank?) or
280 282
          # filter doesn't require any value
281
          ["o", "c", "!*", "*", "t", "ld", "w", "lw", "l2w", "m", "lm", "y"].include? operator_for(field)
283
          ["o", "c", "!*", "*", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", "*&o", "!|c"].include? operator_for(field)
282 284
    end if filters
283 285
  end
284 286

  
config/locales/en-GB.yml
1065 1065
  permission_view_private_notes: View private notes
1066 1066
  permission_set_notes_private: Set notes as private
1067 1067
  label_no_issues_in_project: no issues in project
1068
  label_any_open_issues: any open issues
1069
  label_none_or_closed_issues: none or closed issues
1068 1070
  label_any: all
1069 1071
  label_last_n_weeks: last %{count} weeks
1070 1072
  setting_cross_project_subtasks: Allow cross-project subtasks
config/locales/en.yml
710 710
  label_any_issues_in_project: any issues in project
711 711
  label_any_issues_not_in_project: any issues not in project
712 712
  label_no_issues_in_project: no issues in project
713
  label_any_open_issues: any open issues
714
  label_none_or_closed_issues: none or closed issues
713 715
  label_day_plural: days
714 716
  label_repository: Repository
715 717
  label_repository_new: New repository
public/javascripts/application.js
275 275
    case "y":
276 276
    case "o":
277 277
    case "c":
278
    case "!|c":
279
    case "*&o":
278 280
      enableValues(field, []);
279 281
      break;
280 282
    case "><":
test/unit/query_test.rb
845 845
    assert_not_include 3, ids
846 846
  end
847 847

  
848
  def test_filter_on_relations_with_any_open_issues
849
    IssueRelation.delete_all
850
    # Issue 1 is blocked by 8, which is closed
851
    IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(1), :issue_to => Issue.find(8))
852
    # Issue 2 is blocked by 3, which is open
853
    IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(2), :issue_to => Issue.find(3))
854

  
855
    query = IssueQuery.new(:name => '_')
856
    query.filters = {"blocked" => {:operator => "*&o", :values => ['']}}
857
    ids = find_issues_with_query(query).map(&:id)
858
    assert_equal [], ids & [1]
859
    assert_include 2, ids
860
  end
861

  
862
  def test_filter_on_relations_with_none_or_closed_issues
863
    IssueRelation.delete_all
864
    # Issue 1 is blocked by 8, which is closed
865
    IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(1), :issue_to => Issue.find(8))
866
    # Issue 2 is blocked by 3, which is open
867
    IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(2), :issue_to => Issue.find(3))
868

  
869
    query = IssueQuery.new(:name => '_')
870
    query.filters = {"blocked" => {:operator => "!|c", :values => ['']}}
871
    ids = find_issues_with_query(query).map(&:id)
872
    assert_equal [], ids & [2]
873
    assert_include 1, ids
874
  end
875

  
848 876
  def test_filter_on_relations_with_no_issues
849 877
    IssueRelation.delete_all
850 878
    IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
(3-3/3)