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

Advanced Search #578

Merged
merged 10 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from 8 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
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,4 @@ gem 'pronto-rubocop', require: false
gem "order_already", "~> 0.3.1"
gem "redcarpet"
gem 'blacklight_range_limit'
gem "blacklight_advanced_search"
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ GEM
bootstrap-sass (~> 3.0)
openseadragon (>= 0.2.0)
rails
blacklight_advanced_search (6.4.1)
blacklight (~> 6.0, >= 6.0.1)
parslet
blacklight_oai_provider (6.1.1)
blacklight (~> 6.0)
oai (~> 1.0)
Expand Down Expand Up @@ -1257,6 +1260,7 @@ DEPENDENCIES
apartment
aws-sdk-sqs
blacklight (~> 6.7)
blacklight_advanced_search
blacklight_oai_provider (~> 6.1, >= 6.1.1)
blacklight_range_limit
bolognese (>= 1.9.10)
Expand Down
2 changes: 2 additions & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@
// this:
//= require 'blacklight_range_limit'

//= require blacklight_advanced_search

3 changes: 3 additions & 0 deletions app/assets/stylesheets/application.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@
* Used by blacklight_range_limit
*= require 'blacklight_range_limit'
*

*= require 'blacklight_advanced_search'

*/
17 changes: 15 additions & 2 deletions app/controllers/catalog_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

class CatalogController < ApplicationController
include BlacklightAdvancedSearch::Controller
include BlacklightRangeLimit::ControllerOverride
include Hydra::Catalog
include Hydra::Controller::ControllerBehavior
Expand Down Expand Up @@ -33,7 +34,10 @@ def self.modified_field
config.advanced_search[:url_key] ||= 'advanced'
config.advanced_search[:query_parser] ||= 'dismax'
config.advanced_search[:form_solr_parameters] ||= {}
config.search_builder_class = Hyrax::CatalogSearchBuilder
config.advanced_search[:form_facet_partial] ||= "advanced_search_facets_as_select"

# Use locally customized AdvSearchBuilder so we can enable blacklight_advanced_search
config.search_builder_class = AdvSearchBuilder

# Show gallery view
config.view.gallery.partials = %i[index_header index]
Expand Down Expand Up @@ -168,7 +172,7 @@ def self.modified_field
# This one uses all the defaults set by the solr request handler. Which
# solr request handler? The one set in config[:default_solr_parameters][:qt],
# since we aren't specifying it otherwise.
config.add_search_field('all_fields', label: 'All Fields', include_in_advanced_search: false) do |field|
config.add_search_field('all_fields', label: 'All Fields', include_in_advanced_search: false, advanced_parse: false) do |field|
all_names = config.show_fields.values.map(&:field).join(" ")
title_name = 'title_tesim'
field.solr_parameters = {
Expand Down Expand Up @@ -363,6 +367,15 @@ def self.modified_field
}
end

config.add_search_field('date') do |field|
solr_name = 'date_ssi'
field.include_in_advanced_search = false
field.solr_local_parameters = {
qf: solr_name,
pf: solr_name
}
end

# "sort results by" select (pulldown)
# label in pulldown is followed by the name of the SOLR field to sort by and
# whether the sort is ascending or descending (it must be asc or desc
Expand Down
7 changes: 7 additions & 0 deletions app/controllers/saved_searches_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class SavedSearchesController < ApplicationController
include Blacklight::SavedSearches

helper BlacklightAdvancedSearch::RenderConstraintsOverride
end
5 changes: 3 additions & 2 deletions app/controllers/search_history_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

class SearchHistoryController < ApplicationController
include Blacklight::SearchHistory

helper BlacklightRangeLimit::ViewHelperOverride
helper RangeLimitHelper
helper BlacklightAdvancedSearch::RenderConstraintsOverride
end
2 changes: 2 additions & 0 deletions app/models/search_builder.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# frozen_string_literal: true

class SearchBuilder < Blacklight::SearchBuilder
# self.default_processor_chain += [:add_advanced_parse_q_to_solr, :add_advanced_search_to_solr]
include Blacklight::Solr::SearchBuilderBehavior
include BlacklightAdvancedSearch::AdvancedSearchBuilder
include BlacklightRangeLimit::RangeLimitBuilder

include Hydra::AccessControlsEnforcement
Expand Down
24 changes: 24 additions & 0 deletions app/search_builders/adv_search_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

class AdvSearchBuilder < Hyrax::CatalogSearchBuilder
self.default_processor_chain += [:add_advanced_parse_q_to_solr, :add_advanced_search_to_solr]
include Blacklight::Solr::SearchBuilderBehavior
include BlacklightAdvancedSearch::AdvancedSearchBuilder
# A Solr param filter that is NOT included by default in the chain,
# but is appended by AdvancedController#index, to do a search
# for facets _ignoring_ the current query, we want the facets
# as if the current query weren't there.
#
# Also adds any solr params set in blacklight_config.advanced_search[:form_solr_parameters]
def facets_for_advanced_search_form(solr_p)
# ensure empty query is all records, to fetch available facets on entire corpus
solr_p["q"] = '{!lucene}*:*'
# explicitly use lucene defType since we are passing a lucene query above (and appears to be required for solr 7)
solr_p["defType"] = 'lucene'
# We only care about facets, we don't need any rows.
solr_p["rows"] = "0"

# Anything set in config as a literal
solr_p.merge!(blacklight_config.advanced_search[:form_solr_parameters]) if blacklight_config.advanced_search[:form_solr_parameters]
end
end
33 changes: 33 additions & 0 deletions app/views/advanced/_advanced_search_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<%# OVERRIDE Blacklight Advanced Search gem v6.4.1 to remove the facet search from the bottom of the partial. %>

<% unless (search_context_str = render_search_to_s( advanced_search_context)).blank? %>
<div class="constraints well search_history">
<h4><%= t 'blacklight_advanced_search.form.search_context' %></h4>
<%= search_context_str %>
</div>
<% end %>

<%= form_tag search_catalog_path, :class => 'advanced form-horizontal', :method => :get do %>

<%= render_hash_as_hidden_fields(advanced_search_context) %>

<div class="input-criteria">

<div class="query-criteria">
<h3 class="query-criteria-heading">
<%= t('blacklight_advanced_search.form.query_criteria_heading_html', :select_menu => select_menu_for_field_operator ) %>
</h3>

<div id="advanced_search">
<%= render 'advanced/advanced_search_fields' %>
</div>
</div>
</div>

<hr>

<div class="sort-submit-buttons clearfix">
<%= render 'advanced_search_submit_btns' %>
</div>

<% end %>
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@



<% if (stats = stats_for_field(field_name)) && stats["missing"] > 0 %>
<% if (stats = stats_for_field(field_name)) && (stats["missing"] > 0) && (controller_name != 'advanced') %>
<ul class="missing list-unstyled facet-values subsection">
<li>
<span class="facet-label">
Expand Down
48 changes: 48 additions & 0 deletions app/views/catalog/_search_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<%# OVERRIDE Hyrax 3.5.0 to include the advanced search button in the search bar %>

<%= form_tag search_form_action, method: :get, class: "form-horizontal search-form", id: "search-form-header", role: "search" do %>
<%= render_hash_as_hidden_fields(search_state.params_for_search.except(:q, :search_field, :qt, :page, :utf8)) %>
<%= hidden_field_tag :search_field, 'all_fields' %>
<div class="form-group">

<label class="control-label col-sm-3" for="search-field-header">
<%= t("hyrax.search.form.q.label", application_name: application_name) %>
</label>

<div class="input-group">
<%= text_field_tag :q, current_search_parameters , class: "q form-control", id: "search-field-header", placeholder: t("hyrax.search.form.q.placeholder") %>

<div class="input-group-btn">
<button type="submit" class="btn btn-primary" id="search-submit-header">
<%= t('hyrax.search.button.html') %>
</button>
<%= link_to "Advanced", "/advanced", class: 'btn btn-default', id: 'advanced-top-button' %>
<% if current_user %>
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">

<span class="sr-only" data-search-element="label"><%= t("hyrax.search.form.option.all.label_long", application_name: application_name) %></span>
<span aria-hidden="true"><%= t("hyrax.search.form.option.all.label_short") %></span>
<span class="caret"></span>
</button>
<%# OVERRIDE here to include the advanced search button in the search bar %>
<ul class="dropdown-menu pull-right">
<li>
<%= link_to t("hyrax.search.form.option.all.label_long", application_name: application_name), "#",
data: { "search-option" => main_app.search_catalog_path, "search-label" => t("hyrax.search.form.option.all.label_short") } %>
</li>
<li>
<%= link_to t("hyrax.search.form.option.my_works.label_long"), "#",
data: { "search-option" => hyrax.my_works_path, "search-label" => t("hyrax.search.form.option.my_works.label_short") } %>
</li>
<li>
<%= link_to t("hyrax.search.form.option.my_collections.label_long"), "#",
data: { "search-option" => hyrax.my_collections_path, "search-label" => t("hyrax.search.form.option.my_collections.label_short") } %>
</li>
<% end %>

</ul>
</div><!-- /.input-group-btn -->
</div><!-- /.input-group -->

</div><!-- /.form-group -->
<% end %>
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
mount Qa::Engine => '/authorities'

mount Blacklight::Engine => '/'
mount BlacklightAdvancedSearch::Engine => '/'

mount Hyrax::Engine, at: '/'
if ENV.fetch('HYKU_BULKRAX_ENABLED', 'true') == 'true'
mount Bulkrax::Engine, at: '/'
Expand Down
27 changes: 27 additions & 0 deletions spec/features/advanced_search_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'Advanced Search', type: :feature, js: true, clean: true do
include Warden::Test::Helpers

context 'with unauthenticated user' do
it 'can perform search' do
visit '/'
fill_in('q', with: 'ambitious aardvark')
click_button('Go')
expect(page).to have_content('ambitious aardvark')
expect(page).to have_content('No results found for your search')
end
it 'can perform advanced search' do
visit '/advanced'
fill_in('Title', with: 'ambitious aardvark')
search_btn = find('#advanced-search-submit')
# we send keys because the mocked web page didn't pick up the css change
# to prevent the footer from covering up the submit button
search_btn.send_keys :enter
expect(page).to have_content('ambitious aardvark')
expect(page).to have_content('No results found for your search')
end
end
end
7 changes: 3 additions & 4 deletions spec/requests/catalog_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,9 @@
connection = RSolr.connect(url: "#{ENV['SOLR_URL']}hydra-cross-search-tenant")
allow_any_instance_of(Blacklight::Solr::Repository).to receive(:build_connection).and_return(connection)
allow(CatalogController).to receive(:blacklight_config).and_return(black_light_config)

# get '/catalog', params: { q: '*' }
# get search_catalog_url, params: { locale: 'en', q: 'test' }
get "http://#{cross_search_tenant_account.cname}/catalog?q=test" # , params: { q: 'test' }
# make sure the blacklight config knows the app uses advanced search
black_light_config.advanced_search = {}
get "http://#{cross_search_tenant_account&.cname}/catalog?q=test"
expect(response.status).to eq(200)
end
end
Expand Down
53 changes: 53 additions & 0 deletions spec/search_builders/adv_search_builder_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

RSpec.describe AdvSearchBuilder do
let(:scope) do
double(blacklight_config: CatalogController.blacklight_config,
current_ability: ability)
end
let(:user) { create(:user) }
let(:ability) { ::Ability.new(user) }
let(:access) { :read }
let(:builder) { described_class.new(scope).with_access(access) }

it "can be instantiated" do
expect(builder).to be_instance_of(described_class)
end

describe ".default_processor_chain" do
subject { described_class.default_processor_chain }

let(:expected_default_processor_chain) do
# Yes there's a duplicate for add_access_controls_to_solr_params; but that does not appear to
# be causing a problem like the duplication and order of the now removed additional
# :add_advanced_parse_q_to_solr, :add_advanced_search_to_solr filters. Those existed in their
# current position and at the end of the array.
#
# When we had those duplicates, the :add_advanced_parse_q_to_solr obliterated the join logic
# for files.
%i[
default_solr_parameters
add_query_to_solr
add_facet_fq_to_solr
add_facetting_to_solr
add_solr_fields_to_query
add_paging_to_solr
add_sorting_to_solr
add_group_config_to_solr
add_facet_paging_to_solr
add_range_limit_params
add_access_controls_to_solr_params
filter_models
only_active_works
add_access_controls_to_solr_params
show_works_or_works_that_contain_files
show_only_active_records
filter_collection_facet_for_access
add_advanced_parse_q_to_solr
add_advanced_search_to_solr
]
end

it { is_expected.to eq(expected_default_processor_chain) }
end
end