mirror of
https://github.com/redmine/redmine.git
synced 2025-11-14 01:06:00 +01:00
Add a button to apply issues filter to search results (#38481).
Patch by Go MAEDA. git-svn-id: https://svn.redmine.org/redmine/trunk@22212 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
@@ -69,4 +69,50 @@ module SearchHelper
|
|||||||
links.map {|link| content_tag('li', link)}.join(' ').html_safe +
|
links.map {|link| content_tag('li', link)}.join(' ').html_safe +
|
||||||
'</ul>'.html_safe) unless links.empty?
|
'</ul>'.html_safe) unless links.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def issues_filter_path(question, options)
|
||||||
|
projects_scope = options[:projects_scope]
|
||||||
|
titles_only = options[:titles_only]
|
||||||
|
all_words = options[:all_words]
|
||||||
|
open_issues = options[:open_issues]
|
||||||
|
|
||||||
|
field_to_search = titles_only ? 'subject' : 'any_searchable'
|
||||||
|
params = {
|
||||||
|
:set_filter => 1,
|
||||||
|
:f => ['status_id', field_to_search],
|
||||||
|
:op => {
|
||||||
|
'status_id' => open_issues ? 'o' : '*',
|
||||||
|
field_to_search => all_words ? '~' : '*~'
|
||||||
|
},
|
||||||
|
:v => {field_to_search => [question]},
|
||||||
|
:sort => 'updated_on:desc'
|
||||||
|
}
|
||||||
|
|
||||||
|
case projects_scope
|
||||||
|
when 'all'
|
||||||
|
# nothing to do
|
||||||
|
when 'my_projects'
|
||||||
|
params[:f] << 'project_id'
|
||||||
|
params[:op]['project_id'] = '='
|
||||||
|
params[:v]['project_id'] = ['mine']
|
||||||
|
when 'bookmarks'
|
||||||
|
params[:f] << 'project_id'
|
||||||
|
params[:op]['project_id'] = '='
|
||||||
|
params[:v]['project_id'] = ['bookmarks']
|
||||||
|
when 'subprojects'
|
||||||
|
params[:f] << 'subproject_id'
|
||||||
|
params[:op]['subproject_id'] = '*'
|
||||||
|
params[:project_id] = @project.id
|
||||||
|
else
|
||||||
|
if @project
|
||||||
|
# current project only
|
||||||
|
params[:f] << 'subproject_id'
|
||||||
|
params[:op]['subproject_id'] = '!*'
|
||||||
|
params[:project_id] = @project.id
|
||||||
|
end
|
||||||
|
# else all projects
|
||||||
|
end
|
||||||
|
|
||||||
|
issues_path(params)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -46,6 +46,11 @@
|
|||||||
<%= render_results_by_type(@result_count_by_type) unless @scope.size == 1 %>
|
<%= render_results_by_type(@result_count_by_type) unless @scope.size == 1 %>
|
||||||
</div>
|
</div>
|
||||||
<h3><%= l(:label_result_plural) %> (<%= @result_count %>)</h3>
|
<h3><%= l(:label_result_plural) %> (<%= @result_count %>)</h3>
|
||||||
|
<% if @result_count_by_type['issues'].to_i > 0 && @search_attachments == '0' %>
|
||||||
|
<p class="buttons">
|
||||||
|
<%= link_to l(:button_apply_issues_filter), issues_filter_path(@question, projects_scope: params[:scope], all_words: @all_words, titles_only: @titles_only, open_issues: @open_issues), :class => 'icon icon-list' %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
<dl id="search-results">
|
<dl id="search-results">
|
||||||
<% @results.each do |e| %>
|
<% @results.each do |e| %>
|
||||||
<dt class="<%= e.event_type %> icon icon-<%= e.event_type %>">
|
<dt class="<%= e.event_type %> icon icon-<%= e.event_type %>">
|
||||||
|
|||||||
@@ -1198,6 +1198,7 @@ en:
|
|||||||
button_edit_object: "Edit %{object_name}"
|
button_edit_object: "Edit %{object_name}"
|
||||||
button_delete_object: "Delete %{object_name}"
|
button_delete_object: "Delete %{object_name}"
|
||||||
button_create_and_follow: Create and follow
|
button_create_and_follow: Create and follow
|
||||||
|
button_apply_issues_filter: Apply issues filter
|
||||||
|
|
||||||
status_active: active
|
status_active: active
|
||||||
status_registered: registered
|
status_registered: registered
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ class SearchControllerTest < Redmine::ControllerTest
|
|||||||
assert_select 'input[name=all_words][checked=checked]'
|
assert_select 'input[name=all_words][checked=checked]'
|
||||||
assert_select 'input[name=titles_only]:not([checked])'
|
assert_select 'input[name=titles_only]:not([checked])'
|
||||||
|
|
||||||
|
assert_select 'p.buttons a', :text => 'Apply issues filter'
|
||||||
assert_select '#search-results' do
|
assert_select '#search-results' do
|
||||||
assert_select 'dt.issue a', :text => /Bug #5/
|
assert_select 'dt.issue a', :text => /Bug #5/
|
||||||
assert_select 'dt.issue-closed a', :text => /Bug #8 \(Closed\)/
|
assert_select 'dt.issue-closed a', :text => /Bug #8 \(Closed\)/
|
||||||
@@ -457,4 +458,15 @@ class SearchControllerTest < Redmine::ControllerTest
|
|||||||
|
|
||||||
assert_select '#search-results dt.project', 0
|
assert_select '#search-results dt.project', 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_search_should_not_show_apply_issues_filter_button_if_no_issues_found
|
||||||
|
get :index, :params => {:q => 'commits'}
|
||||||
|
assert_response :success
|
||||||
|
|
||||||
|
assert_select 'p.buttons a', :text => 'Apply issues filter', :count => 0
|
||||||
|
assert_select '#search-results' do
|
||||||
|
assert_select 'dt.issue', :count => 0
|
||||||
|
assert_select 'dt.issue-closed', :count => 0
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -54,4 +54,36 @@ class SearchHelperTest < Redmine::HelperTest
|
|||||||
r
|
r
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_issues_filter_path
|
||||||
|
# rubocop:disable Layout/LineLength
|
||||||
|
assert_equal(
|
||||||
|
'/issues?f[]=status_id&f[]=any_searchable&f[]=project_id&op[any_searchable]=*~&op[project_id]==&op[status_id]=*&set_filter=1&sort=updated_on:desc&v[any_searchable][]=recipe&v[project_id][]=mine',
|
||||||
|
Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'my_projects'))
|
||||||
|
)
|
||||||
|
assert_equal(
|
||||||
|
'/issues?f[]=status_id&f[]=any_searchable&f[]=project_id&op[any_searchable]=*~&op[project_id]==&op[status_id]=*&set_filter=1&sort=updated_on:desc&v[any_searchable][]=recipe&v[project_id][]=bookmarks',
|
||||||
|
Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'bookmarks'))
|
||||||
|
)
|
||||||
|
assert_equal(
|
||||||
|
'/issues?f[]=status_id&f[]=any_searchable&op[any_searchable]=*~&op[status_id]=*&set_filter=1&sort=updated_on:desc&v[any_searchable][]=recipe',
|
||||||
|
Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'all'))
|
||||||
|
)
|
||||||
|
# f[]=subject
|
||||||
|
assert_equal(
|
||||||
|
'/issues?f[]=status_id&f[]=subject&op[status_id]=*&op[subject]=*~&set_filter=1&sort=updated_on:desc&v[subject][]=recipe',
|
||||||
|
Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'all', titles_only: '1'))
|
||||||
|
)
|
||||||
|
# op[subject]=~ (contains)
|
||||||
|
assert_equal(
|
||||||
|
'/issues?f[]=status_id&f[]=subject&op[status_id]=*&op[subject]=~&set_filter=1&sort=updated_on:desc&v[subject][]=recipe',
|
||||||
|
Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'all', titles_only: '1', all_words: ''))
|
||||||
|
)
|
||||||
|
# op[status_id]=o (open)
|
||||||
|
assert_equal(
|
||||||
|
'/issues?f[]=status_id&f[]=subject&op[status_id]=o&op[subject]=*~&set_filter=1&sort=updated_on:desc&v[subject][]=recipe',
|
||||||
|
Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'all', titles_only: '1', open_issues: '1'))
|
||||||
|
)
|
||||||
|
# rubocop:enable Layout/LineLength
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user