Patch #43917 » 0001-Add-default-any_searchable-filter.patch
| app/models/issue_query.rb | ||
|---|---|---|
| 103 | 103 | |
| 104 | 104 |
def initialize(attributes=nil, *args) |
| 105 | 105 |
super(attributes) |
| 106 |
self.filters ||= {'status_id' => {:operator => "o", :values => [""]}}
|
|
| 106 |
self.filters ||= {
|
|
| 107 |
'status_id' => {:operator => "o", :values => [""]},
|
|
| 108 |
'any_searchable' => {:operator => "~", :values => [""]}
|
|
| 109 |
} |
|
| 107 | 110 |
end |
| 108 | 111 | |
| 109 | 112 |
def draw_relations |
| app/models/query.rb | ||
|---|---|---|
| 347 | 347 |
:tree => ["=", "~", "!*", "*"] |
| 348 | 348 |
} |
| 349 | 349 | |
| 350 |
NO_VALUE_REQUIRED_OPERATORS = %w[o c !* * nd t ld nw w lw l2w nm m lm y *o !o].freeze |
|
| 351 | ||
| 350 | 352 |
class_attribute :available_columns |
| 351 | 353 |
self.available_columns = [] |
| 352 | 354 | |
| ... | ... | |
| 526 | 528 |
# filter requires one or more values |
| 527 | 529 |
(values_for(field) and values_for(field).first.present?) or |
| 528 | 530 |
# filter doesn't require any value |
| 529 |
["o", "c", "!*", "*", "nd", "t", "ld", "nw", "w", "lw", "l2w", "nm", "m", "lm", "y", "*o", "!o"].include? operator_for(field) |
|
| 531 |
NO_VALUE_REQUIRED_OPERATORS.include?(operator_for(field)) or |
|
| 532 |
# filter with blank value is skipped only for :search filters |
|
| 533 |
skip_filter_for_blank_value?(field, operator_for(field), values_for(field)) |
|
| 530 | 534 |
end if filters |
| 531 | 535 |
end |
| 532 | 536 | |
| ... | ... | |
| 993 | 997 |
next unless v and !v.empty? |
| 994 | 998 | |
| 995 | 999 |
operator = operator_for(field) |
| 1000 |
next if skip_filter_for_blank_value?(field, operator, v) |
|
| 996 | 1001 | |
| 997 | 1002 |
# "me" value substitution |
| 998 | 1003 |
if %w(assigned_to_id author_id user_id watcher_id updated_by last_updated_by).include?(field) |
| ... | ... | |
| 1099 | 1104 | |
| 1100 | 1105 |
private |
| 1101 | 1106 | |
| 1107 |
def skip_filter_for_blank_value?(field, operator, values) |
|
| 1108 |
return false unless type_for(field) == :search |
|
| 1109 |
return false if NO_VALUE_REQUIRED_OPERATORS.include?(operator) |
|
| 1110 | ||
| 1111 |
values = Array(values) |
|
| 1112 |
values.none?(&:present?) |
|
| 1113 |
end |
|
| 1114 | ||
| 1102 | 1115 |
def grouped_query(&) |
| 1103 | 1116 |
r = nil |
| 1104 | 1117 |
if grouped? |
| test/functional/issues_controller_test.rb | ||
|---|---|---|
| 157 | 157 |
assert_response :success |
| 158 | 158 | |
| 159 | 159 |
# default filter |
| 160 |
assert_query_filters [['status_id', 'o', '']] |
|
| 160 |
assert_query_filters [ |
|
| 161 |
['status_id', 'o', ''], |
|
| 162 |
['any_searchable', '~', ''] |
|
| 163 |
] |
|
| 161 | 164 |
end |
| 162 | 165 | |
| 163 | 166 |
def test_index_with_project_and_filter |
| ... | ... | |
| 237 | 240 |
'*' => {:op => '*', :values => ['']}
|
| 238 | 241 |
} |
| 239 | 242 |
} |
| 240 |
default_filter = {'status_id' => {:operator => 'o', :values => ['']}}
|
|
| 243 |
default_filter = {
|
|
| 244 |
'status_id' => {:operator => 'o', :values => ['']},
|
|
| 245 |
'any_searchable' => {:operator => '~', :values => ['']}
|
|
| 246 |
} |
|
| 241 | 247 |
to_test.each do |field, expression_and_expected| |
| 242 | 248 |
expression_and_expected.each do |filter_expression, expected| |
| 243 | 249 |
get(:index, :params => {:set_filter => 1, field => filter_expression})
|
| test/unit/query_test.rb | ||
|---|---|---|
| 1010 | 1010 |
assert_equal [1, 3], find_issues_with_query(query).map(&:id).sort |
| 1011 | 1011 |
end |
| 1012 | 1012 | |
| 1013 |
def test_filter_that_does_not_require_value_should_not_be_skipped |
|
| 1014 |
open_issue = Issue.generate!(:status => IssueStatus.where(:is_closed => false).first) |
|
| 1015 |
closed_issue = Issue.generate!(:status => IssueStatus.where(:is_closed => true).first) |
|
| 1016 | ||
| 1017 |
query = IssueQuery.new( |
|
| 1018 |
:name => '_', |
|
| 1019 |
:filters => {
|
|
| 1020 |
'status_id' => {:operator => 'o', :values => ['']}
|
|
| 1021 |
} |
|
| 1022 |
) |
|
| 1023 | ||
| 1024 |
assert query.valid? |
|
| 1025 |
assert_includes query.issues, open_issue |
|
| 1026 |
assert_not_includes query.issues, closed_issue |
|
| 1027 |
end |
|
| 1028 | ||
| 1013 | 1029 |
def test_filter_any_searchable |
| 1014 | 1030 |
User.current = User.find(1) |
| 1015 | 1031 |
query = IssueQuery.new( |
| ... | ... | |
| 1025 | 1041 |
assert_equal [1, 2, 3], result.map(&:id).sort |
| 1026 | 1042 |
end |
| 1027 | 1043 | |
| 1044 |
def test_filter_any_searchable_with_blank_value_should_be_noop |
|
| 1045 |
User.current = User.find(1) |
|
| 1046 | ||
| 1047 |
base_query = IssueQuery.new( |
|
| 1048 |
:name => '_', |
|
| 1049 |
:filters => {
|
|
| 1050 |
'status_id' => {:operator => 'o', :values => ['']}
|
|
| 1051 |
} |
|
| 1052 |
) |
|
| 1053 |
query = IssueQuery.new( |
|
| 1054 |
:name => '_', |
|
| 1055 |
:filters => {
|
|
| 1056 |
'status_id' => {:operator => 'o', :values => ['']},
|
|
| 1057 |
'any_searchable' => {:operator => '~', :values => ['']}
|
|
| 1058 |
} |
|
| 1059 |
) |
|
| 1060 | ||
| 1061 |
assert query.valid? |
|
| 1062 |
assert_equal base_query.statement, query.statement |
|
| 1063 |
assert_equal base_query.issues.pluck(:id).sort, query.issues.pluck(:id).sort |
|
| 1064 |
end |
|
| 1065 | ||
| 1066 |
def test_filter_any_searchable_with_partially_blank_value_should_be_invalid |
|
| 1067 |
set_language_if_valid 'en' |
|
| 1068 |
User.current = User.find(1) |
|
| 1069 | ||
| 1070 |
query = IssueQuery.new( |
|
| 1071 |
:name => '_', |
|
| 1072 |
:filters => {
|
|
| 1073 |
'status_id' => {:operator => 'o', :values => ['']},
|
|
| 1074 |
'any_searchable' => {:operator => '><', :values => ['', 'recipe']}
|
|
| 1075 |
} |
|
| 1076 |
) |
|
| 1077 | ||
| 1078 |
assert_not query.valid? |
|
| 1079 |
assert_include 'Any searchable text cannot be blank', query.errors.full_messages |
|
| 1080 |
end |
|
| 1081 | ||
| 1028 | 1082 |
def test_filter_any_searchable_with_multiple_words |
| 1029 | 1083 |
User.current = User.find(1) |
| 1030 | 1084 |
query = IssueQuery.new( |
- « Previous
- 1
- 2
- Next »