Skip to content
Draft
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
43 changes: 21 additions & 22 deletions app/controllers/concerns/blacklight/search_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Blacklight::SearchContext
# own controller.
included do
if respond_to? :helper_method
helper_method :current_search_session, :search_session
helper_method :current_search_session, :search_session, :page_links_document_path
end
end

Expand All @@ -31,23 +31,17 @@ def searches_from_history
# GET previous and next document json for the document specified by
# the counter param in current search
def page_links
counter_param = params.delete(:counter)
@page_link_data = {}
if counter_param
index = counter_param.to_i - 1
response, documents = search_service.previous_and_next_documents_for_search index, search_state.reset_search
if documents.detect(&:present?)
@page_link_data[:prev] = page_links_document_path(documents.first, index)
@page_link_data[:next] = page_links_document_path(documents.last, index + 2)
end
if response&.total&.positive?
@page_link_data[:counterRaw] = counter_param
@page_link_data[:counterDelimited] = helpers.number_with_delimiter(counter_param.to_i)
@page_link_data[:totalRaw] = response.total
@page_link_data[:totalDelimited] = helpers.number_with_delimiter(response.total)
end
counter = if Rails::VERSION::MAJOR >= 8
params.expect(:counter).to_i
else
params[:counter].to_i
end

@search_context = load_search_context(counter, search_state.reset_search)

respond_to do |format|
format.json
end
render json: @page_link_data
end

private
Expand Down Expand Up @@ -142,11 +136,9 @@ def setup_next_and_previous_documents
return { counter: params[:counter] } if setup_next_and_previous_on_client?
return nil unless setup_next_and_previous_on_server?

index = search_session['counter'].to_i - 1
response, documents = search_service.previous_and_next_documents_for_search index, search_state.reset(current_search_session.query_params)

search_session['total'] = response.total
{ prev: documents.first, next: documents.last }
load_search_context(search_session['counter'].to_i, search_state.reset(current_search_session.query_params)).tap do |search_context_presenter|
search_session['total'] = search_context_presenter.total
end
rescue Blacklight::Exceptions::InvalidRequest => e
logger&.warn "Unable to setup next and previous documents: #{e}"
nil
Expand All @@ -166,4 +158,11 @@ def page_links_document_path(document, counter)

solr_document_path(document, counter: counter)
end

def load_search_context(counter, context_search_state)
index = counter - 1
response, _documents = search_service.previous_and_next_documents_for_search index, context_search_state

Blacklight::SearchContextPresenter.new(response, counter: counter, view_context: view_context)
end
end
40 changes: 40 additions & 0 deletions app/presenters/blacklight/search_context_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

module Blacklight
# Presenter for the search context (e.g. previous + next links) of a single document within a search result.
class SearchContextPresenter
attr_reader :response, :counter, :view_context

def initialize(response, view_context:, counter: nil)
@response = response
@counter = counter
@view_context = view_context
end

# Provide backwards-compatibility for downstream code expecting the old hash-based response.
delegate_missing_to :to_hash

def to_hash
@to_hash ||= {
prev: previous_document,
next: next_document
}
end

def total
response.total.to_i
end

def previous_document
return if counter && counter <= 1

response.documents.first
end

def next_document
return if counter && counter >= response.total

response.documents.last
end
end
end
10 changes: 10 additions & 0 deletions app/views/catalog/page_links.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

if @search_context.previous_document || @search_context.next_document
json.prev page_links_document_path(@search_context.previous_document, @search_context.counter - 1) if @search_context.previous_document
json.next page_links_document_path(@search_context.next_document, @search_context.counter + 1) if @search_context.next_document
json.counterRaw @search_context.counter
json.totalRaw @search_context.total
json.counterDelimited number_with_delimiter(@search_context.counter) if @search_context.counter
json.totalDelimited number_with_delimiter(@search_context.total) if @search_context.total.positive?
end
21 changes: 13 additions & 8 deletions spec/controllers/catalog_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,11 @@
context 'and no exception is raised' do
before do
expect(search_service).to receive(:previous_and_next_documents_for_search)
.and_return([double(total: 5), [double("a"), mock_document, double("b")]])
.and_return([double(total: 5, documents: documents), documents])
end

let(:documents) { [double("a"), mock_document, double("b")] }

it "sets previous document" do
get :show, params: { id: doc_id }
expect(assigns[:search_context][:prev]).not_to be_nil
Expand Down Expand Up @@ -788,17 +790,20 @@ def export_as_mock
end

describe "page_links" do
render_views

it "has prev/next docs and result set data for non-empty result sets", :integration do
get :page_links, params: { f: { "format" => 'Book' }, counter: 2 }
expect(assigns(:page_link_data)).not_to be_empty
expect(assigns(:page_link_data).fetch(:prev, nil)).to end_with('counter=1')
expect(assigns(:page_link_data).fetch(:next, nil)).to end_with('counter=3')
expect(assigns(:page_link_data).fetch(:totalRaw, nil)).to be 30
get :page_links, params: { f: { "format" => 'Book' }, counter: 2, format: 'json' }

expect(response.parsed_body).not_to be_empty
expect(response.parsed_body.fetch(:prev, nil)).to end_with('counter=1')
expect(response.parsed_body.fetch(:next, nil)).to end_with('counter=3')
expect(response.parsed_body.fetch(:totalRaw, nil)).to be 30
end

it "is empty for empty result sets", :integration do
get :page_links, params: { f: { "format" => ['empty-result-set'] }, counter: 1 }
expect(assigns(:page_link_data)).to be_empty
get :page_links, params: { f: { "format" => ['empty-result-set'] }, counter: 1, format: 'json' }
expect(response.parsed_body).to be_empty
end
end
end
Expand Down
Loading