Project

General

Profile

Feature #38481 » filter-search-results.patch

Go MAEDA, 2023-04-20 17:13

View differences:

app/helpers/search_helper.rb
69 69
        links.map {|link| content_tag('li', link)}.join(' ').html_safe +
70 70
        '</ul>'.html_safe) unless links.empty?
71 71
  end
72

  
73
  def issues_filter_path(question, options)
74
    projects_scope = options[:projects_scope]
75
    titles_only = options[:titles_only]
76
    all_words = options[:all_words]
77
    open_issues = options[:open_issues]
78

  
79
    field_to_search = titles_only ? 'subject' : 'any_searchable'
80
    params = {
81
      :set_filter => 1,
82
      :f => ['status_id', field_to_search],
83
      :op => {
84
        'status_id' => open_issues ? 'o' : '*',
85
        field_to_search => all_words ? '~' : '*~'
86
      },
87
      :v => {field_to_search => [question]},
88
      :sort => 'updated_on:desc'
89
    }
90

  
91
    case projects_scope
92
    when 'all'
93
      # nothing to do
94
    when 'my_projects'
95
      params[:f] << 'project_id'
96
      params[:op]['project_id'] = '='
97
      params[:v]['project_id'] = ['mine']
98
    when 'bookmarks'
99
      params[:f] << 'project_id'
100
      params[:op]['project_id'] = '='
101
      params[:v]['project_id'] = ['bookmarks']
102
    when 'subprojects'
103
      params[:f] << 'subproject_id'
104
      params[:op]['subproject_id'] = '*'
105
      params[:project_id] = @project.id
106
    else
107
      if @project
108
        # current project only
109
        params[:f] << 'subproject_id'
110
        params[:op]['subproject_id'] = '!*'
111
        params[:project_id] = @project.id
112
      end
113
      # else all projects
114
    end
115

  
116
    issues_path(params)
117
  end
72 118
end
app/views/search/index.html.erb
46 46
      <%= render_results_by_type(@result_count_by_type) unless @scope.size == 1 %>
47 47
    </div>
48 48
    <h3><%= l(:label_result_plural) %> (<%= @result_count %>)</h3>
49
    <% if @result_count_by_type['issues'].to_i > 0 && @search_attachments == '0' %>
50
      <p class="buttons">
51
        <%= 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' %>
52
      </p>
53
    <% end %>
49 54
    <dl id="search-results">
50 55
      <% @results.each do |e| %>
51 56
        <dt class="<%= e.event_type %> icon icon-<%= e.event_type %>">
config/locales/en.yml
1199 1199
  button_edit_object: "Edit %{object_name}"
1200 1200
  button_delete_object: "Delete %{object_name}"
1201 1201
  button_create_and_follow: Create and follow
1202
  button_apply_issues_filter: Apply issues filter
1202 1203

  
1203 1204
  status_active: active
1204 1205
  status_registered: registered
test/functional/search_controller_test.rb
94 94
    assert_select 'input[name=all_words][checked=checked]'
95 95
    assert_select 'input[name=titles_only]:not([checked])'
96 96

  
97
    assert_select 'p.buttons a', :text => 'Apply issues filter'
97 98
    assert_select '#search-results' do
98 99
      assert_select 'dt.issue a', :text => /Bug #5/
99 100
      assert_select 'dt.issue-closed a', :text => /Bug #8 \(Closed\)/
......
456 457

  
457 458
    assert_select '#search-results dt.project', 0
458 459
  end
460

  
461
  def test_search_should_not_show_apply_issues_filter_button_if_no_issues_found
462
    get :index, :params => {:q => 'commits'}
463
    assert_response :success
464

  
465
    assert_select 'p.buttons a', :text => 'Apply issues filter', :count => 0
466
    assert_select '#search-results' do
467
      assert_select 'dt.issue', :count => 0
468
      assert_select 'dt.issue-closed', :count => 0
469
    end
470
  end
459 471
end
test/helpers/search_helper_test.rb
54 54
      r
55 55
    )
56 56
  end
57

  
58
  def test_issues_filter_path
59
    # rubocop:disable Layout/LineLength
60
    assert_equal(
61
      '/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',
62
      Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'my_projects'))
63
    )
64
    assert_equal(
65
      '/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',
66
      Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'bookmarks'))
67
    )
68
    assert_equal(
69
      '/issues?f[]=status_id&f[]=any_searchable&op[any_searchable]=*~&op[status_id]=*&set_filter=1&sort=updated_on:desc&v[any_searchable][]=recipe',
70
      Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'all'))
71
    )
72
    # f[]=subject
73
    assert_equal(
74
      '/issues?f[]=status_id&f[]=subject&op[status_id]=*&op[subject]=*~&set_filter=1&sort=updated_on:desc&v[subject][]=recipe',
75
      Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'all', titles_only: '1'))
76
    )
77
    # op[subject]=~ (contains)
78
    assert_equal(
79
      '/issues?f[]=status_id&f[]=subject&op[status_id]=*&op[subject]=~&set_filter=1&sort=updated_on:desc&v[subject][]=recipe',
80
      Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'all', titles_only: '1', all_words: ''))
81
    )
82
    # op[status_id]=o (open)
83
    assert_equal(
84
      '/issues?f[]=status_id&f[]=subject&op[status_id]=o&op[subject]=*~&set_filter=1&sort=updated_on:desc&v[subject][]=recipe',
85
      Addressable::URI.unencode(issues_filter_path('recipe', projects_scope: 'all', titles_only: '1', open_issues: '1'))
86
    )
87
    # rubocop:enable Layout/LineLength
88
  end
57 89
end
(3-3/3)