Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/assets/stylesheets/base/_facets.scss
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ ul.unstyled {
width: 100%;
}

.nav-item > a {
.nav-item > a, .nav-item > span {
position: relative;
display: block;
color: #333;
Expand Down
8 changes: 8 additions & 0 deletions app/controllers/concerns/searchable_index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module SearchableIndex
included do
attr_reader :facet_fields, :search_params, :facet_params, :page, :sort_by, :index_resources
before_action :set_params, only: [:index, :count]
before_action :limit_filters, only: [:index, :count]
before_action :fetch_resources, only: [:index, :count]
Comment thread
fbacall marked this conversation as resolved.

helper 'search'
Expand Down Expand Up @@ -141,4 +142,11 @@ def pagination_params
def search_and_facet_params
params.permit(*(@model.search_and_facet_keys | [:page_size, :page_number, :page, :per_page]))
end

def limit_filters
if !request.format.json? && !request.format.json_api? && current_user.nil? && @facet_params&.values &&
TeSS::Config.filter_limit && @facet_params.values.flatten.length > TeSS::Config.filter_limit
handle_error(400, t('search.errors.filter_limit_reached'))
end
end
Comment thread
fbacall marked this conversation as resolved.
end
15 changes: 14 additions & 1 deletion app/helpers/search_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,22 @@ def filter_link(name, value, count, html_options = {}, &block)
parameters.delete('page') #remove the page option if it exists
html_options.reverse_merge!(title: value.to_s)

link_to parameters, html_options do
content = -> do
if block_given?
block.call
else
content_tag(:span, facet_title(name, value, html_options), class: 'facet-label') +
content_tag(:span, "#{count}", class: 'facet-count')
end
end

if filter_limit_reached?
html_options[:class] = [html_options[:class], 'filter-limit-reached'].compact.join(' ')

content_tag(:span, html_options, &content)
else
link_to parameters, html_options, &content
end
end

def remove_filter_link(name, value, html_options = {}, &block)
Expand Down Expand Up @@ -75,4 +83,9 @@ def toggle_hidden_facet_link facet
<i class='glyphicon glyphicon-chevron-up pull-right toggle-#{facet}' style='display: none;'></i>
".html_safe
end

def filter_limit_reached?
current_user.nil? && @facet_params&.values && TeSS::Config.filter_limit &&
@facet_params.values.flatten.length >= TeSS::Config.filter_limit
end
Comment thread
fbacall marked this conversation as resolved.
end
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<li class="toggle-wrap mb-2 nav-item">
<%= filter_link(facet_field, 'true', count) do %>
<label class="toggle">
<input type="checkbox">
<input type="checkbox" <%= 'disabled' if filter_limit_reached? -%>>
<span class="slider round"></span>
</label>
<%= enable_text %>
Expand Down
3 changes: 3 additions & 0 deletions app/views/search/common/_search_panel.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<%= content_for(:display_options) %>
</div>
<% if TeSS::Config.solr_enabled %>
<% if filter_limit_reached? %>
<div class="alert alert-info mb-3"><%= t('search.errors.filter_limit_reached') %></div>
<% end %>
<div class="hidden-xs">
<%= render partial: 'search/common/search_filters', locals: { resources: resources } %>
</div>
Expand Down
6 changes: 4 additions & 2 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,6 @@ en:
Groups is a feature which for now is used only to manage access of private spaces.
A user being part of a group has access to every private space which requires the group.
Each group has multiple owners. A owner can add and remove people to the group.
orcid:
orcid:
error: 'An error occurred whilst trying to authenticate your ORCID.'
link: 'Link your ORCID'
Expand Down Expand Up @@ -1240,4 +1239,7 @@ en:
info: "This %{resource_type} originated from another TeSS registry. For complete, up-to-date information, please visit the original entry:"
link: Go to original entry
other_space:
link: View in space
link: View in space
search:
errors:
filter_limit_reached: Filter limit reached, please log in to apply additional filters.
1 change: 1 addition & 0 deletions config/tess.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ default: &default
space:
primary: '#260252'
secondary: '#5c29b1'
filter_limit: # Maximum number of filter values allowed for anonymous users
development:
<<: *default

Expand Down
79 changes: 79 additions & 0 deletions test/controllers/materials_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1763,4 +1763,83 @@ class MaterialsControllerTest < ActionController::TestCase
assert_select '#space-info', count: 0
end
end

test 'displays warning when filter limit reached for anonymous users' do
with_settings(solr_enabled: true, filter_limit: 2) do
Material.stub(:search_and_filter, MockSearch.new(Material.all)) do
get :index, params: { keywords: ['dancing', 'singing'] }

assert_response :success
end
end

assert_select 'div.alert', text: /Filter limit reached/
assert_select '.facet-option.filter-limit-reached'
end

test 'does not display filter limit warning for logged-in users' do
sign_in(@user)

with_settings(solr_enabled: true, filter_limit: 2) do
Material.stub(:search_and_filter, MockSearch.new(Material.all)) do
get :index, params: { keywords: ['dancing', 'singing'] }

assert_response :success
end
end

assert_select 'div.alert', text: /Filter limit reached/, count: 0
assert_select '.facet-option.filter-limit-reached', count: 0
end

test 'throws error if filter limit exceeded for anonymous users' do
with_settings(solr_enabled: true, filter_limit: 2) do
Material.stub(:search_and_filter, MockSearch.new(Material.all)) do
get :index, params: { keywords: ['dancing', 'singing', 'acrobatics'] }

assert_response :bad_request
end
end

assert_select '#error-message', text: /Filter limit reached/
end

test 'does not throw error if filter limit exceeded for logged-in users' do
sign_in(@user)

with_settings(solr_enabled: true, filter_limit: 2) do
Material.stub(:search_and_filter, MockSearch.new(Material.all)) do
get :index, params: { keywords: ['dancing', 'singing', 'acrobatics'] }

assert_response :success
end
end

assert_select '#error-message', count: 0
assert_select 'div.alert', text: /Filter limit reached/, count: 0
assert_select '.facet-option.filter-limit-reached', count: 0
end

test 'does not throw error if filter limit exceeded for API requests' do
with_settings(solr_enabled: true, filter_limit: 2) do
Material.stub(:search_and_filter, MockSearch.new(Material.all)) do
get :index, params: { keywords: ['dancing', 'singing', 'acrobatics'], format: :json_api }

assert_response :success
assert_not_nil assigns(:materials)
assert_valid_json_api_response
body = nil
assert_nothing_raised do
body = JSON.parse(response.body)
end

assert body['data'].any?
assert body['meta']['results-count'] > 0
assert_includes body['meta']['facets']['keywords'], 'acrobatics'
assert body['meta']['available-facets'].keys.any?
assert body['meta']['available-facets'].values.any?
assert body['links']['self'].include?('acrobatics')
end
end
end
end