diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2016-05-06 18:59:36 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2016-05-06 18:59:36 +0000 |
commit | 699a75910db7e7e4caafaee19808a8a80d9acceb (patch) | |
tree | 973755cce7a6c567292024b4e6d1f7bf146423f0 | |
parent | 860ae0631ad5514a08db6ac980c1b0ff3bbb170a (diff) | |
download | redmine-699a75910db7e7e4caafaee19808a8a80d9acceb.tar.gz redmine-699a75910db7e7e4caafaee19808a8a80d9acceb.zip |
Filter by issue id (#4806).
A shortcut is added to the context menu to filter the selected issues.
git-svn-id: http://svn.redmine.org/redmine/trunk@15371 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r-- | app/models/issue_query.rb | 11 | ||||
-rw-r--r-- | app/models/query.rb | 15 | ||||
-rw-r--r-- | app/views/context_menus/issues.html.erb | 5 | ||||
-rw-r--r-- | config/locales/en.yml | 1 | ||||
-rw-r--r-- | config/locales/fr.yml | 1 | ||||
-rw-r--r-- | public/javascripts/application.js | 4 | ||||
-rw-r--r-- | public/stylesheets/application.css | 1 | ||||
-rw-r--r-- | test/unit/query_test.rb | 8 |
8 files changed, 39 insertions, 7 deletions
diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb index c97de0a19..c4ab37d59 100644 --- a/app/models/issue_query.rb +++ b/app/models/issue_query.rb @@ -245,6 +245,8 @@ class IssueQuery < Query add_available_filter "parent_id", :type => :tree, :label => :field_parent_issue add_available_filter "child_id", :type => :tree, :label => :label_subtask_plural + add_available_filter "issue_id", :type => :integer, :label => :label_issue + Tracker.disabled_core_fields(trackers).each {|field| delete_available_filter field } @@ -509,6 +511,15 @@ class IssueQuery < Query end end + def sql_for_issue_id_field(field, operator, value) + ids = value.first.to_s.scan(/\d+/).map(&:to_i).join(",") + if ids.present? + "#{Issue.table_name}.id IN (#{ids})" + else + "1=0" + end + 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 3a30e2769..68beb3c97 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -264,9 +264,9 @@ class Query < ActiveRecord::Base if values_for(field) case type_for(field) when :integer - add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^[+-]?\d+$/) } + add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/\A[+-]?\d+(,[+-]?\d+)*\z/) } when :float - add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/^[+-]?\d+(\.\d*)?$/) } + add_filter_error(field, :invalid) if values_for(field).detect {|v| v.present? && !v.match(/\A[+-]?\d+(\.\d*)?\z/) } when :date, :date_past case operator_for(field) when "=", ">=", "<=", "><" @@ -771,10 +771,15 @@ class Query < ActiveRecord::Base when :date, :date_past sql = date_clause(db_table, db_field, parse_date(value.first), parse_date(value.first), is_custom_filter) when :integer - if is_custom_filter - 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})" + int_values = value.first.to_s.scan(/[+-]?\d+/).map(&:to_i).join(",") + if int_values.present? + if is_custom_filter + 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}))" + else + sql = "#{db_table}.#{db_field} IN (#{int_values})" + end else - sql = "#{db_table}.#{db_field} = #{value.first.to_i}" + sql = "1=0" end when :float if is_custom_filter diff --git a/app/views/context_menus/issues.html.erb b/app/views/context_menus/issues.html.erb index df3d73e9b..891432054 100644 --- a/app/views/context_menus/issues.html.erb +++ b/app/views/context_menus/issues.html.erb @@ -133,6 +133,11 @@ <li><%= watcher_link(@issues, User.current) %></li> <% end %> +<% unless @issue %> + <li><%= context_menu_link l(:button_filter), _project_issues_path(@project, :set_filter => 1, :issue_id => @issue_ids.join(",")), + :class => 'icon-list' %></li> +<% end %> + <% if @issue.present? %> <% if @can[:log_time] -%> <li><%= context_menu_link l(:button_log_time), new_issue_time_entry_path(@issue), diff --git a/config/locales/en.yml b/config/locales/en.yml index 52489ce38..06bed1870 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1044,6 +1044,7 @@ en: button_close: Close button_reopen: Reopen button_import: Import + button_filter: Filter status_active: active status_registered: registered diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 0ba07d23a..a8e7e5c46 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1054,6 +1054,7 @@ fr: button_close: Fermer button_reopen: Réouvrir button_import: Importer + button_filter: Filtrer status_active: actif status_registered: enregistré diff --git a/public/javascripts/application.js b/public/javascripts/application.js index ef1070c0e..985467b4c 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -219,8 +219,8 @@ function buildFilterRow(field, operator, values) { case "float": case "tree": tr.find('td.values').append( - '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' + - ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" /></span>' + '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="14" class="value" /></span>' + + ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="14" class="value" /></span>' ); $('#values_'+fieldId+'_1').val(values[0]); $('#values_'+fieldId+'_2').val(values[1]); diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 28f8213ab..253cfbdf9 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -1181,6 +1181,7 @@ a.icon-only::after { .icon-ok { background-image: url(../images/true.png); } .icon-not-ok { background-image: url(../images/false.png); } .icon-link-break { background-image: url(../images/link_break.png); } +.icon-list { background-image: url(../images/text_list_bullets.png); } .icon-file { background-image: url(../images/files/default.png); } .icon-file.text-plain { background-image: url(../images/files/text.png); } diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index cb01bcba8..588f5fafd 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -235,6 +235,14 @@ class QueryTest < ActiveSupport::TestCase assert_equal 2, issues.first.id end + def test_operator_is_on_integer_should_accept_comma_separated_values + query = IssueQuery.new(:name => '_') + query.add_filter("issue_id", '=', ['1,3']) + issues = find_issues_with_query(query) + assert_equal 2, issues.size + assert_equal [1,3], issues.map(&:id).sort + end + def test_operator_is_on_integer_custom_field f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_for_all => true, :is_filter => true, :trackers => Tracker.all) CustomValue.create!(:custom_field => f, :customized => Issue.find(1), :value => '7') |