Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Blacklight hit-highlighting in the full-text field #1030

Merged
merged 1 commit into from
Dec 20, 2017
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/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
//= require blacklight_gallery
//= require blacklight_heatmaps
//= require blacklight_oembed
//= require full_text_collapse
//= require index_status_typeahead
//= require nested_related_items
//= require openseadragon
Expand All @@ -37,4 +38,3 @@
// For blacklight_range_limit built-in JS, if you don't want it you don't need
// this:
//= require 'blacklight_range_limit'

23 changes: 23 additions & 0 deletions app/assets/javascripts/full_text_collapse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* global Blacklight */

Blacklight.onLoad(function(){

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'Blacklight' is not defined.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This addressed by the global above.

var uniqueId = (function() {
var uuid = 0;

return function(el) {
el.id = 'ui-id-' + ( ++uuid );
};
} )();

$('dd.blacklight-full_text_tesimv').addClass('collapse').each(function() {
$(this).attr('id', uniqueId(this));
});

$('dt.blacklight-full_text_tesimv').each(function() {
$(this).text($(this).text().replace(/:$/, ''));
$(this).attr('data-toggle', 'collapse');
$(this).attr('data-target', '#' + $(this).next('dd').attr('id'));
});

$('dd.blacklight-full_text_tesimv').collapse({ toggle: false });
});
1 change: 1 addition & 0 deletions app/assets/stylesheets/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
@import "viewers";
@import "modules/view_metadata";
@import "modules/related_item";
@import "modules/full_text_highlight";
32 changes: 32 additions & 0 deletions app/assets/stylesheets/modules/full_text_highlight.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
dt.blacklight-full_text_tesimv {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid qualifying class selectors with an element.

Copy link
Contributor Author

@jkeck jkeck Dec 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We unfortunately have to provide element because the same class is on two elements that we want to treat differently. This was pulled over from the previous PR, and seems like is safe to ignore in this case.

@extend .h4;
cursor: pointer;
display: inline-block;
float: none;
text-align: initial;
width: auto;
// collapse carets shamelessly stolen from blacklight facets
&[data-toggle="collapse"]::after {
// symbol for "opening" panels
content: "\e114";
float: right;
font-family: "Glyphicons Halflings";
font-size: 0.8em;
line-height: normal;
padding-left: 2ch;
}

&.collapsed::after {
// symbol for "collapsed" panels
content: "\e080";
}
}

dd.blacklight-full_text_tesimv {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid qualifying class selectors with an element.

float: none;
margin-left: 0;

em {
font-weight: bold;
}
}
33 changes: 32 additions & 1 deletion app/controllers/catalog_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ class CatalogController < ApplicationController
## Default parameters to send to solr for all search-like requests. See also SolrHelper#solr_search_params
config.default_solr_params = {
qt: 'search',
fl: '*'
fl: '*',
hl: true,
'hl.fl' => 'full_text_tesimv',
'hl.snippets' => 5,
'hl.fragsize' => 240,
'hl.mergeContiguous' => true,
'hl.useFastVectorHighlighter' => true
}

config.default_autocomplete_solr_params = {
Expand Down Expand Up @@ -208,6 +214,18 @@ class CatalogController < ApplicationController
config.add_index_field 'manuscript_number_tesim', label: 'Manuscript number'
config.add_index_field 'range_labels_tesim', label: 'Section'
config.add_index_field 'related_document_id_ssim', label: 'Manuscript', helper_method: :manuscript_link
config.add_index_field(
'full_text_tesimv',
if: lambda do |*args|
# bail out to true (show the field) if we don't have 3 arguments (context being the added argument)
# This is required for the metadata configuration admin page to return the field properly.
return true if args.length < 3
full_text_highlight_exists_in_response?(*args)
end,
label: 'Preview matches in document text',
highlight: true,
helper_method: :render_fulltext_highlight
)
# "fielded" search configuration. Used by pulldown among other places.
# For supported keys in hash, see rdoc for Blacklight::SearchFields
#
Expand Down Expand Up @@ -352,4 +370,17 @@ def metadata
def start_new_search_session?
super && params[:format] != 'json'
end

class << self
# Blacklight's highlighting feature assumes that the metadata exists in the page
# and replaces the rendered version from the dopcument with that of the highlighting
# section. In the case of our full text field, we do not render it in the normal results
# so we need to not display the field at all unless it was returned in the highlighting.
def full_text_highlight_exists_in_response?(context, config, document)
response = context.instance_variable_get(:@response)
document_highlight = response.dig('highlighting', document['id'])
return true if document_highlight.present? && document_highlight[config.key].present?
false
end
end
end
9 changes: 9 additions & 0 deletions app/helpers/catalog_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ def manuscript_link(options = {})
link_to link_title, spotlight.exhibit_solr_document_path(current_exhibit, druid)
end

def render_fulltext_highlight(args)
return if args[:value].blank?
safe_join(args[:value].map do |val|
content_tag('p') do
val
end
end, '')
end

private

def thumbnail_tag_image_path(document)
Expand Down
34 changes: 34 additions & 0 deletions spec/features/full_text_highlight_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.feature 'Full text highlighting' do
let(:exhibit) { create(:exhibit) }
let(:dor_harvester) { DorHarvester.new(druid_list: druid, exhibit: exhibit) }

before do
allow(Spotlight::Engine.config).to receive(:filter_resources_by_exhibit).and_return(false)
end

context 'when a document has a full text highlight hit' do
it 'shows the full-text hightlight field and provides a toggle', js: true do
visit spotlight.search_exhibit_catalog_path(exhibit, q: 'structure')

expect(page).to have_css('dt', text: 'Preview matches in document text')

expect(page).not_to have_css('dd p', text: 'about need for data structures capable of storing', visible: true)
page.find('dt', text: 'Preview matches in document text').click
expect(page).to have_css('dd p', text: 'about need for data structures capable of storing', visible: true)
end
end

context 'when a document does not have a full text highlight hit' do
it 'does not include full-text highlight', js: true do
visit spotlight.search_exhibit_catalog_path(exhibit, q: 'Maps')

expect(page).to have_css('.documents-list .document') # there are results

expect(page).not_to have_css('dt', text: 'Preview matches in document text')
end
end
end
56 changes: 56 additions & 0 deletions spec/fixtures/sample_solr_docs.json

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions spec/helpers/catalog_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,19 @@ def current_exhibit
end
end
end

describe '#render_fulltext_highlight' do
context 'when there is no value' do
it 'is nil' do
expect(helper.render_fulltext_highlight(value: [])).to be_nil
end
end

context 'when there are values' do
it 'wraps each value in a paragraph tag' do
ps = helper.render_fulltext_highlight(value: %w(Value1 Value2))
expect(ps).to eq '<p>Value1</p><p>Value2</p>'
end
end
end
end