##// END OF EJS Templates
Filter by issue id (#4806)....
Jean-Philippe Lang -
r14989:699a75910db7
parent child
Show More
@@ -245,6 +245,8 class IssueQuery < Query
245 add_available_filter "parent_id", :type => :tree, :label => :field_parent_issue
245 add_available_filter "parent_id", :type => :tree, :label => :field_parent_issue
246 add_available_filter "child_id", :type => :tree, :label => :label_subtask_plural
246 add_available_filter "child_id", :type => :tree, :label => :label_subtask_plural
247
247
248 add_available_filter "issue_id", :type => :integer, :label => :label_issue
249
248 Tracker.disabled_core_fields(trackers).each {|field|
250 Tracker.disabled_core_fields(trackers).each {|field|
249 delete_available_filter field
251 delete_available_filter field
250 }
252 }
@@ -509,6 +511,15 class IssueQuery < Query
509 end
511 end
510 end
512 end
511
513
514 def sql_for_issue_id_field(field, operator, value)
515 ids = value.first.to_s.scan(/\d+/).map(&:to_i).join(",")
516 if ids.present?
517 "#{Issue.table_name}.id IN (#{ids})"
518 else
519 "1=0"
520 end
521 end
522
512 def sql_for_relations(field, operator, value, options={})
523 def sql_for_relations(field, operator, value, options={})
513 relation_options = IssueRelation::TYPES[field]
524 relation_options = IssueRelation::TYPES[field]
514 return relation_options unless relation_options
525 return relation_options unless relation_options
@@ -264,9 +264,9 class Query < ActiveRecord::Base
264 if values_for(field)
264 if values_for(field)
265 case type_for(field)
265 case type_for(field)
266 when :integer
266 when :integer
267 add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^[+-]?\d+$/) }
267 add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/\A[+-]?\d+(,[+-]?\d+)*\z/) }
268 when :float
268 when :float
269 add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^[+-]?\d+(\.\d*)?$/) }
269 add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/\A[+-]?\d+(\.\d*)?\z/) }
270 when :date, :date_past
270 when :date, :date_past
271 case operator_for(field)
271 case operator_for(field)
272 when "=", ">=", "<=", "><"
272 when "=", ">=", "<=", "><"
@@ -771,10 +771,15 class Query < ActiveRecord::Base
771 when :date, :date_past
771 when :date, :date_past
772 sql = date_clause(db_table, db_field, parse_date(value.first), parse_date(value.first), is_custom_filter)
772 sql = date_clause(db_table, db_field, parse_date(value.first), parse_date(value.first), is_custom_filter)
773 when :integer
773 when :integer
774 if is_custom_filter
774 int_values = value.first.to_s.scan(/[+-]?\d+/).map(&:to_i).join(",")
775 sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) = #{value.first.to_i})"
775 if int_values.present?
776 if is_custom_filter
777 sql = "(#{db_table}.#{db_field} <> '' AND CAST(CASE #{db_table}.#{db_field} WHEN '' THEN '0' ELSE #{db_table}.#{db_field} END AS decimal(30,3)) IN (#{int_values}))"
778 else
779 sql = "#{db_table}.#{db_field} IN (#{int_values})"
780 end
776 else
781 else
777 sql = "#{db_table}.#{db_field} = #{value.first.to_i}"
782 sql = "1=0"
778 end
783 end
779 when :float
784 when :float
780 if is_custom_filter
785 if is_custom_filter
@@ -133,6 +133,11
133 <li><%= watcher_link(@issues, User.current) %></li>
133 <li><%= watcher_link(@issues, User.current) %></li>
134 <% end %>
134 <% end %>
135
135
136 <% unless @issue %>
137 <li><%= context_menu_link l(:button_filter), _project_issues_path(@project, :set_filter => 1, :issue_id => @issue_ids.join(",")),
138 :class => 'icon-list' %></li>
139 <% end %>
140
136 <% if @issue.present? %>
141 <% if @issue.present? %>
137 <% if @can[:log_time] -%>
142 <% if @can[:log_time] -%>
138 <li><%= context_menu_link l(:button_log_time), new_issue_time_entry_path(@issue),
143 <li><%= context_menu_link l(:button_log_time), new_issue_time_entry_path(@issue),
@@ -1044,6 +1044,7 en:
1044 button_close: Close
1044 button_close: Close
1045 button_reopen: Reopen
1045 button_reopen: Reopen
1046 button_import: Import
1046 button_import: Import
1047 button_filter: Filter
1047
1048
1048 status_active: active
1049 status_active: active
1049 status_registered: registered
1050 status_registered: registered
@@ -1054,6 +1054,7 fr:
1054 button_close: Fermer
1054 button_close: Fermer
1055 button_reopen: Réouvrir
1055 button_reopen: Réouvrir
1056 button_import: Importer
1056 button_import: Importer
1057 button_filter: Filtrer
1057
1058
1058 status_active: actif
1059 status_active: actif
1059 status_registered: enregistré
1060 status_registered: enregistré
@@ -219,8 +219,8 function buildFilterRow(field, operator, values) {
219 case "float":
219 case "float":
220 case "tree":
220 case "tree":
221 tr.find('td.values').append(
221 tr.find('td.values').append(
222 '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' +
222 '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="14" class="value" /></span>' +
223 ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" /></span>'
223 ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="14" class="value" /></span>'
224 );
224 );
225 $('#values_'+fieldId+'_1').val(values[0]);
225 $('#values_'+fieldId+'_1').val(values[0]);
226 $('#values_'+fieldId+'_2').val(values[1]);
226 $('#values_'+fieldId+'_2').val(values[1]);
@@ -1181,6 +1181,7 a.icon-only::after {
1181 .icon-ok { background-image: url(../images/true.png); }
1181 .icon-ok { background-image: url(../images/true.png); }
1182 .icon-not-ok { background-image: url(../images/false.png); }
1182 .icon-not-ok { background-image: url(../images/false.png); }
1183 .icon-link-break { background-image: url(../images/link_break.png); }
1183 .icon-link-break { background-image: url(../images/link_break.png); }
1184 .icon-list { background-image: url(../images/text_list_bullets.png); }
1184
1185
1185 .icon-file { background-image: url(../images/files/default.png); }
1186 .icon-file { background-image: url(../images/files/default.png); }
1186 .icon-file.text-plain { background-image: url(../images/files/text.png); }
1187 .icon-file.text-plain { background-image: url(../images/files/text.png); }
@@ -235,6 +235,14 class QueryTest < ActiveSupport::TestCase
235 assert_equal 2, issues.first.id
235 assert_equal 2, issues.first.id
236 end
236 end
237
237
238 def test_operator_is_on_integer_should_accept_comma_separated_values
239 query = IssueQuery.new(:name => '_')
240 query.add_filter("issue_id", '=', ['1,3'])
241 issues = find_issues_with_query(query)
242 assert_equal 2, issues.size
243 assert_equal [1,3], issues.map(&:id).sort
244 end
245
238 def test_operator_is_on_integer_custom_field
246 def test_operator_is_on_integer_custom_field
239 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all)
247 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all)
240 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
248 CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7')
General Comments 0
You need to be logged in to leave comments. Login now