Skip to content

Commit

Permalink
Move facet prefix logic into the facet models, and display facet inde…
Browse files Browse the repository at this point in the history
…x navigation as a bootstrap pagination widget
  • Loading branch information
cbeer committed Oct 17, 2015
1 parent 73da742 commit 4bd3f56
Show file tree
Hide file tree
Showing 22 changed files with 148 additions and 48 deletions.
17 changes: 6 additions & 11 deletions app/assets/stylesheets/blacklight/_facets.scss
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,14 @@ ul.facet_extended_list, .facet_extended_list ul

// Facet modal alphabetical filter
.alpha-filter {
margin-bottom: 18px;
text-align: center;

a {
padding: 0 2px;

&.active {
color: inherit;
font-weight: bold;
}
.btn {
vertical-align: top;
}
}

.pagination {
margin: 0;
}
}

@media (max-width: $grid-float-breakpoint) {

Expand Down
10 changes: 10 additions & 0 deletions app/assets/stylesheets/blacklight/_pagination.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@
text-align: center ;
}


.pagination-xs {
li {
a,
span {
border: none;
padding: $padding-xs-vertical $padding-xs-horizontal;
}
}
}
6 changes: 0 additions & 6 deletions app/helpers/blacklight/facets_helper_behavior.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ def has_facet_values? fields = facet_field_names, options = {}
facets_from_request(fields).any? { |display_facet| !display_facet.items.empty? && should_render_facet?(display_facet) }
end

##
# The querystring params without the facet filter, used for index navigation#
def params_no_facet_filter
params.except(:'facet.prefix')
end

##
# Render a collection of facet fields.
# @see #render_facet_limit
Expand Down
20 changes: 9 additions & 11 deletions app/views/catalog/_facet_index_navigation.html.erb
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<% if @facet.index_pagination && @display_facet.sort == 'index' %>
<div id="facet-index-navigation" class="alpha-filter">
<span id="facet-index-label"><%= t('blacklight.search.facets.filter') %></span>
<span id="facet-index-letters">
<% unless params[:'facet.prefix'].blank? %><%= link_to(t('blacklight.search.facets.clear'), @pagination.params_for_resort_url('index', params.except(:'facet.prefix')), data: {ajax_modal: "preserve"}) %><% end %>
<% @facet.index_range.each do |letter| %>
<%= link_to(letter, @pagination.params_for_resort_url('index', params.merge(:'facet.prefix'=> letter)), data: {ajax_modal: "preserve"}, class: (params[:'facet.prefix']==letter ? 'active' : '')) %>
<% end %>
</span>
</div>
<% end %>
<nav class="alpha-filter">
<%= link_to t('blacklight.search.facets.clear'), @pagination.params_for_resort_url('index', params.except(@pagination.request_keys[:prefix])), data: { ajax_modal: "preserve" }, class: ['btn btn-default btn-xs', ('disabled' unless @pagination.prefix.present?)].join(' ') %>

<ol class="pagination pagination-xs">
<% @facet.index_range.each do |letter| %>
<li class="<%= 'active' if @pagination.prefix == letter %>"><%= link_to(letter, @pagination.params_for_resort_url('index', params.merge(@pagination.request_keys[:prefix] => letter)), data: { ajax_modal: "preserve" }) %></li>
<% end %>
</ol>
</nav>
4 changes: 2 additions & 2 deletions app/views/catalog/facet.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
</div>

<div class="modal-header">
<%= render partial: 'facet_index_navigation' if @facet.index_range && @display_facet.index? %>

<button type="button" class="ajax-modal-close close" data-dismiss="modal" aria-hidden="true">×</button>

<h3 class="modal-title"><%= facet_field_label(@facet.key) %></h3>
<%= render partial: 'facet_index_navigation' if @facet.index_range && @display_facet.index? %>

</div>
<div class="modal-body">
<div class="facet_extended_list">
Expand Down
1 change: 0 additions & 1 deletion config/locales/blacklight.de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ de:
counter: '%{counter}. '
facets:
title: 'Beschränken dein Suche'
filter: 'Filter:'
clear: 'Löschen'
sort:
count: 'Numerisch ordnen'
Expand Down
3 changes: 1 addition & 2 deletions config/locales/blacklight.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,7 @@ en:
counter: '%{counter}. '
facets:
title: 'Limit your search'
filter: 'Filter:'
clear: 'Clear'
clear: 'Clear Filter'
sort:
count: 'Numerical Sort'
index: 'A-Z Sort'
Expand Down
1 change: 0 additions & 1 deletion config/locales/blacklight.es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ es:
counter: '%{counter}.'
facets:
title: 'Limite su búsqueda'
filter: 'Límite:'
clear: 'Borrar'
sort:
count: 'Ordenación numérica'
Expand Down
1 change: 0 additions & 1 deletion config/locales/blacklight.fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ fr:
unselect: 'Panier'
facets:
title: 'Limiter votre recherche'
filter: 'Filtre:'
clear: 'Effacer'
sort:
count: 'Du + au - fréquent'
Expand Down
1 change: 0 additions & 1 deletion config/locales/blacklight.it.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ it:
counter: '%{counter}. '
facets:
title: 'Affina la ricerca'
filter: 'Limite:'
clear: 'Cancella'
sort:
count: 'Ordina per numero'
Expand Down
1 change: 0 additions & 1 deletion config/locales/blacklight.pt-BR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ pt-BR:
counter: '%{counter}. '
facets:
title: 'Filtre sua busca'
filter: 'Filtre:'
clear: 'Limpar'
sort:
count: 'Ordenar por Número'
Expand Down
1 change: 1 addition & 0 deletions lib/blacklight/facet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def facet_paginator(field_config, display_facet)
display_facet.items,
sort: display_facet.sort,
offset: display_facet.offset,
prefix: display_facet.prefix,
limit: facet_limit_for(field_config.key)
)
end
Expand Down
17 changes: 12 additions & 5 deletions lib/blacklight/facet_paginator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ class FacetPaginator
# and need to make them accessible in a list so we can easily
# strip em out before redirecting to catalog/index.
mattr_accessor :request_keys do
{ sort: :'facet.sort', page: :'facet.page' }
{ sort: :'facet.sort', page: :'facet.page', prefix: :'facet.prefix' }
end

if Rails.version < "4.1"
self.request_keys = { sort: :'facet.sort', page: :'facet.page' }
self.request_keys = { sort: :'facet.sort', page: :'facet.page', prefix: :'facet.prefix' }
end

attr_reader :offset, :limit, :sort
attr_reader :offset, :limit, :sort, :prefix

# all_facet_values is a list of facet value objects returned by solr,
# asking solr for n+1 facet values.
Expand All @@ -35,6 +35,7 @@ def initialize(all_facet_values, arguments = {})
@offset = arguments[:offset].to_s.to_i
@limit = arguments[:limit]
@sort = arguments[:sort]
@prefix = arguments[:prefix]

@all = all_facet_values
end
Expand Down Expand Up @@ -84,10 +85,16 @@ def total_pages
# under facet.sort ), and your current request params.
# Get back params suitable to passing to an ActionHelper method for
# creating a url, to resort by that method.
def params_for_resort_url(sort_method, params)
def params_for_resort_url(sort_method, params = {})
# When resorting, we've got to reset the offset to start at beginning,
# no way to make it make sense otherwise.
params.merge(request_keys[:sort] => sort_method, request_keys[:page] => nil)
resort_params = params.merge(request_keys[:sort] => sort_method, request_keys[:page] => nil)

if sort_method == 'count'
resort_params.except!(request_keys[:prefix])
end

resort_params
end

def as_json(_ = nil)
Expand Down
1 change: 0 additions & 1 deletion lib/blacklight/search_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ def fetch(id=nil, extra_controller_params={})
# @return [Blacklight::SolrResponse] the solr response
def get_facet_field_response(facet_field, user_params = params || {}, extra_controller_params = {})
query = search_builder.with(user_params).facet(facet_field)
extra_controller_params.merge!({:"facet.prefix"=>user_params[:"facet.prefix"]}) unless user_params[:"facet.prefix"].blank?
repository.search(query.merge(extra_controller_params))
end

Expand Down
4 changes: 4 additions & 0 deletions lib/blacklight/solr/search_builder_behavior.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ def add_facet_paging_to_solr(solr_params)
offset = (page - 1) * (limit)

sort = blacklight_params[request_keys[:sort]]
prefix = blacklight_params[request_keys[:prefix]]

# Need to set as f.facet_field.facet.* to make sure we
# override any field-specific default in the solr request handler.
Expand All @@ -224,6 +225,9 @@ def add_facet_paging_to_solr(solr_params)
if blacklight_params[request_keys[:sort]]
solr_params[:"f.#{facet}.facet.sort"] = sort
end
if blacklight_params[request_keys[:prefix]]
solr_params[:"f.#{facet}.facet.prefix"] = prefix
end
solr_params[:rows] = 0
end

Expand Down
21 changes: 20 additions & 1 deletion lib/blacklight/solr_response/facets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ def sort
def offset
@options[:offset] || solr_default_offset
end

def prefix
@options[:prefix] || solr_default_prefix
end

def index?
sort == 'index'
end

def count?
sort == 'count'
end

private
# Per https://wiki.apache.org/solr/SimpleFacetParameters#facet.limit
Expand All @@ -65,7 +77,10 @@ def solr_default_sort
def solr_default_offset
0
end


def solr_default_prefix
nil
end
end

##
Expand Down Expand Up @@ -150,6 +165,10 @@ def facet_field_aggregations
options[:offset] = (params[:"f.#{facet_field_name}.facet.offset"] || params[:'facet.offset']).to_i
end

if params[:"f.#{facet_field_name}.facet.prefix"] || params[:'facet.prefix']
options[:prefix] = (params[:"f.#{facet_field_name}.facet.prefix"] || params[:'facet.prefix'])
end

hash[facet_field_name] = FacetField.new(facet_field_name, items, options)

if blacklight_config and !blacklight_config.facet_fields[facet_field_name]
Expand Down
6 changes: 3 additions & 3 deletions spec/features/facets_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@
end
expect(page).to have_selector '.facet-values li:first', text: "Accident insurance"
expect(page).to have_css '.facet-values li', count: 20
find(:css,".facet_pagination.bottom").click_on "B"
click_on 'B'
expect(page).to have_selector '.facet-values li:first', text: "Buddhism"
expect(page).to have_css '.facet-values li', count: 1
find(:css,".facet_pagination.bottom").click_on "T"
click_on 'T'
expect(page).to have_selector '.facet-values li:first', text: "Teaching"
expect(page).to have_css '.facet-values li', count: 4
find(:css,".facet_pagination.bottom").click_on "Clear"
click_on 'Clear Filter'
expect(page).to have_selector '.facet-values li:first', text: "Accident insurance"
expect(page).to have_css '.facet-values li', count: 20
find(:css,".facet_pagination.bottom").click_on "Numerical Sort"
Expand Down
12 changes: 12 additions & 0 deletions spec/lib/blacklight/facet_paginator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@
expect(click_params[ sort_key ]).to eq 'count'
expect(click_params[ page_key ]).to be_nil
end

context 'when sorting by "count"' do
subject { described_class.new([]) }

it 'includes the prefix filter for "index" sorting' do
expect(subject.params_for_resort_url('index', :'facet.prefix' => 'A')).to include :'facet.prefix' => 'A'
end

it 'removes the prefix filter' do
expect(subject.params_for_resort_url('count', :'facet.prefix' => 'A')).not_to include :'facet.prefix' => 'A'
end
end
end

context "for a nil :limit" do
Expand Down
8 changes: 8 additions & 0 deletions spec/lib/blacklight/solr/search_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@
let(:facet_field) { 'format' }
let(:sort_key) { Blacklight::Solr::FacetPaginator.request_keys[:sort] }
let(:page_key) { Blacklight::Solr::FacetPaginator.request_keys[:page] }
let(:prefix_key) { Blacklight::Solr::FacetPaginator.request_keys[:prefix] }

let(:blacklight_config) do
Blacklight::Configuration.new do |config|
Expand Down Expand Up @@ -612,6 +613,13 @@
expect(solr_parameters[:"f.#{facet_field}.facet.sort"]).to eq 'index'
end
end

context 'when a prefix is provided' do
let(:user_params) { { prefix_key => 'A' } }
it 'includes the prefix in the query' do
expect(solr_parameters[:"f.#{facet_field}.facet.prefix"]).to eq 'A'
end
end
end

describe "#with_tag_ex" do
Expand Down
19 changes: 19 additions & 0 deletions spec/lib/blacklight/solr_response/facets_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,30 @@

it "should default to count if no value is found and the default limit is used" do
expect(subject.aggregations['my_field'].sort).to eq 'count'
expect(subject.aggregations['my_field'].count?).to eq true
end

it "should default to index if no value is found and the limit is unlimited" do
request_params['facet.limit'] = -1
expect(subject.aggregations['my_field'].sort).to eq 'index'
expect(subject.aggregations['my_field'].index?).to eq true
end
end

describe '#prefix' do
it 'extracts field-specific prefix values' do
request_params['f.my_field.facet.prefix'] = "a"
request_params['facet.prefix'] = "b"
expect(subject.aggregations['my_field'].prefix).to eq 'a'
end

it "extracts a global sort value" do
request_params['facet.prefix'] = "abc"
expect(subject.aggregations['my_field'].prefix).to eq 'abc'
end

it "defaults to no prefix value" do
expect(subject.aggregations['my_field'].prefix).to be_nil
end
end
end
Expand Down
40 changes: 40 additions & 0 deletions spec/views/catalog/_facet_index_navigation.html.erb_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require 'spec_helper'

describe 'catalog/_facet_index_navigation.html.erb', type: :view do
let(:pagination) { Blacklight::Solr::FacetPaginator.new([]) }
let(:facet) { Blacklight::Configuration::FacetField.new({ index_range: '0'..'9' })}

before do
assign(:pagination, pagination)
assign(:facet, facet)
end

it 'renders the facet index navigation range' do
render

expect(rendered).to have_selector '.pagination'
expect(rendered).to have_link '0', href: '/?facet.prefix=0&facet.sort=index'
expect(rendered).to have_link '1'
expect(rendered).to have_link '8'
expect(rendered).to have_link '9'
end

it 'renders a "clear filter" button' do
render
expect(rendered).to have_selector '.btn.disabled', text: 'Clear Filter'
end

context 'with a selected index' do
let(:pagination) { Blacklight::Solr::FacetPaginator.new([], prefix: '5') }

it 'highlights the selected index' do
render
expect(rendered).to have_selector '.active', text: '5'
end

it 'enables the clear facets button' do
render
expect(rendered).to have_link 'Clear Filter'
end
end
end
2 changes: 1 addition & 1 deletion spec/views/catalog/_facets.html.erb_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
before do
blacklight_config.facet_fields['facet_field_1'] = facet_field

@mock_display_facet_1 = double(:name => 'facet_field_1', sort: nil, offset: nil, :items => [Blacklight::SolrResponse::Facets::FacetItem.new(:value => 'Value', :hits => 1234)])
@mock_display_facet_1 = double(:name => 'facet_field_1', sort: nil, offset: nil, prefix: nil, :items => [Blacklight::SolrResponse::Facets::FacetItem.new(:value => 'Value', :hits => 1234)])
allow(view).to receive_messages(:facet_field_names => [:facet_field_1],
:facet_limit_for => 10 )

Expand Down

0 comments on commit 4bd3f56

Please sign in to comment.