blacklight 7.33.1 → 7.35.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.env +1 -0
- data/.github/workflows/ruby.yml +21 -1
- data/.rubocop.yml +2 -0
- data/Gemfile +4 -0
- data/VERSION +1 -1
- data/app/components/blacklight/advanced_search_form_component.html.erb +1 -1
- data/app/components/blacklight/advanced_search_form_component.rb +5 -5
- data/app/components/blacklight/content_areas_shim.rb +1 -1
- data/app/components/blacklight/document/action_component.html.erb +2 -9
- data/app/components/blacklight/document/action_component.rb +18 -0
- data/app/components/blacklight/document/actions_component.rb +1 -1
- data/app/components/blacklight/document_component.rb +33 -10
- data/app/components/blacklight/document_metadata_component.html.erb +4 -2
- data/app/components/blacklight/document_metadata_component.rb +6 -2
- data/app/components/blacklight/facet_field_checkboxes_component.html.erb +2 -2
- data/app/components/blacklight/facet_field_list_component.html.erb +2 -2
- data/app/components/blacklight/header_component.html.erb +2 -0
- data/app/components/blacklight/header_component.rb +26 -0
- data/app/components/blacklight/metadata_field_component.html.erb +2 -2
- data/app/components/blacklight/metadata_field_layout_component.rb +7 -4
- data/app/components/blacklight/response/pagination_component.html.erb +1 -1
- data/app/components/blacklight/response/pagination_component.rb +5 -1
- data/app/components/blacklight/response/view_type_component.rb +1 -1
- data/app/components/blacklight/search_navbar_component.html.erb +5 -0
- data/app/components/blacklight/search_navbar_component.rb +34 -0
- data/app/components/blacklight/system/dropdown_component.rb +2 -2
- data/app/components/blacklight/system/flash_message_component.rb +1 -1
- data/app/components/blacklight/top_navbar_component.html.erb +12 -0
- data/app/components/blacklight/top_navbar_component.rb +17 -0
- data/app/controllers/concerns/blacklight/base.rb +5 -0
- data/app/controllers/concerns/blacklight/bookmarks.rb +5 -1
- data/app/controllers/concerns/blacklight/catalog.rb +14 -3
- data/app/controllers/concerns/blacklight/controller.rb +3 -2
- data/app/helpers/blacklight/blacklight_helper_behavior.rb +2 -2
- data/app/helpers/blacklight/render_partials_helper_behavior.rb +1 -0
- data/app/models/concerns/blacklight/document/active_model_shim.rb +10 -0
- data/app/models/concerns/blacklight/document/attributes.rb +50 -0
- data/app/models/concerns/blacklight/document.rb +12 -20
- data/app/models/search.rb +6 -1
- data/app/presenters/blacklight/rendering/join.rb +1 -1
- data/app/services/blacklight/field_retriever.rb +13 -11
- data/app/values/blacklight/types.rb +99 -11
- data/app/views/catalog/_document.html.erb +1 -1
- data/app/views/catalog/_facet_layout.html.erb +2 -2
- data/app/views/catalog/_search_form.html.erb +1 -1
- data/app/views/catalog/_show_main_content.html.erb +2 -2
- data/app/views/catalog/_show_sidebar.html.erb +1 -1
- data/app/views/catalog/_show_tools.html.erb +4 -3
- data/app/views/catalog/facet.html.erb +3 -3
- data/app/views/layouts/blacklight/base.html.erb +7 -7
- data/app/views/shared/_header_navbar.html.erb +1 -22
- data/blacklight.gemspec +3 -4
- data/config/locales/blacklight.en.yml +1 -0
- data/docker-compose.yml +1 -0
- data/lib/blacklight/configuration.rb +39 -2
- data/lib/blacklight/engine.rb +15 -0
- data/lib/blacklight/solr/repository.rb +14 -2
- data/lib/blacklight/solr/request.rb +2 -0
- data/lib/blacklight/solr/search_builder_behavior.rb +2 -1
- data/lib/blacklight.rb +1 -1
- data/lib/generators/blacklight/assets_generator.rb +1 -1
- data/lib/generators/blacklight/install_generator.rb +1 -1
- data/lib/generators/blacklight/templates/catalog_controller.rb +4 -0
- data/lib/generators/blacklight/templates/solr/conf/solrconfig.xml +69 -0
- data/lib/generators/blacklight/templates/solr_document.rb +1 -1
- data/lib/railties/blacklight.rake +4 -4
- data/package.json +1 -1
- data/spec/components/blacklight/document_component_spec.rb +60 -11
- data/spec/components/blacklight/facet_component_spec.rb +11 -1
- data/spec/components/blacklight/facet_item_pivot_component_spec.rb +3 -2
- data/spec/components/blacklight/header_component_spec.rb +20 -0
- data/spec/components/blacklight/search_bar_component_spec.rb +1 -1
- data/spec/controllers/blacklight/base_spec.rb +1 -1
- data/spec/features/advanced_search_spec.rb +56 -0
- data/spec/features/axe_spec.rb +5 -0
- data/spec/features/sitelinks_search_box_spec.rb +13 -0
- data/spec/helpers/blacklight/search_history_constraints_helper_behavior_spec.rb +8 -15
- data/spec/helpers/blacklight_helper_spec.rb +10 -5
- data/spec/models/blacklight/configuration_spec.rb +22 -0
- data/spec/models/blacklight/solr/repository_spec.rb +27 -0
- data/spec/models/blacklight/solr/search_builder_spec.rb +16 -0
- data/spec/models/solr_document_spec.rb +21 -3
- data/spec/presenters/blacklight/show_presenter_spec.rb +4 -10
- data/spec/services/blacklight/field_retriever_spec.rb +17 -0
- data/spec/spec_helper.rb +32 -5
- data/spec/support/view_component_test_helpers.rb +35 -0
- data/spec/views/catalog/_show_tools.html.erb_spec.rb +24 -10
- metadata +30 -27
- data/spec/features/sitelinks_search_box.rb +0 -13
- data/spec/support/view_component_capybara_test_helpers.rb +0 -8
@@ -270,9 +270,9 @@ module Blacklight::BlacklightHelperBehavior
|
|
270
270
|
#
|
271
271
|
# @param [Hash] query_params the query parameters to check
|
272
272
|
# @return [Symbol]
|
273
|
-
def document_index_view_type query_params = params
|
273
|
+
def document_index_view_type query_params = params || {}
|
274
274
|
view_param = query_params[:view]
|
275
|
-
view_param ||= session[:preferred_view]
|
275
|
+
view_param ||= session[:preferred_view] if respond_to?(:session)
|
276
276
|
if view_param && document_index_views.key?(view_param.to_sym)
|
277
277
|
view_param.to_sym
|
278
278
|
else
|
@@ -69,6 +69,7 @@ module Blacklight::RenderPartialsHelperBehavior
|
|
69
69
|
if template
|
70
70
|
template.render(self, locals.merge(document: doc))
|
71
71
|
else
|
72
|
+
logger.warn("No template was found for base_name: '#{base_name}', view_type: '#{view_type}' in render_document_partial")
|
72
73
|
''
|
73
74
|
end
|
74
75
|
end
|
@@ -28,6 +28,16 @@ module Blacklight::Document
|
|
28
28
|
def find id
|
29
29
|
repository.find(id).documents.first
|
30
30
|
end
|
31
|
+
|
32
|
+
# In Rails 7.1+, needs this method
|
33
|
+
def composite_primary_key?
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
# In Rails 7.1+, needs this method
|
38
|
+
def has_query_constraints?
|
39
|
+
false
|
40
|
+
end
|
31
41
|
end
|
32
42
|
|
33
43
|
##
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_model/conversion'
|
4
|
+
|
5
|
+
module Blacklight::Document
|
6
|
+
module Attributes
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
class_attribute :attribute_types, instance_accessor: false
|
11
|
+
self.attribute_types = Hash.new(Blacklight::Types::Value)
|
12
|
+
end
|
13
|
+
|
14
|
+
class_methods do
|
15
|
+
# Define an attribute reader on a document model
|
16
|
+
# @param [Symbol] name the name of the attribute to define
|
17
|
+
# @param [Symbol, Class] type the type of the attribute to define
|
18
|
+
# @param [String] field the name of the document's field to use for this attribute
|
19
|
+
# @param [any, Proc] default the default value for the attribute
|
20
|
+
# @example
|
21
|
+
# class SolrDocument
|
22
|
+
# include Blacklight::Solr::Document
|
23
|
+
# attribute :title, :string, 'title_tesim'
|
24
|
+
#
|
25
|
+
# Deprecated syntax:
|
26
|
+
# attribute :title, Blacklight::Types::String, 'title_tesim'
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# doc = SolrDocument.new(title_tesim: ["One flew over the cuckoo's nest"])
|
30
|
+
# doc.title
|
31
|
+
# #=> "One flew over the cuckoo's nest"
|
32
|
+
def attribute(name, type = :value, deprecated_field = name, field: nil, default: nil, **kwargs)
|
33
|
+
field ||= deprecated_field
|
34
|
+
|
35
|
+
define_method name do
|
36
|
+
if type.respond_to?(:coerce) && !(type < Blacklight::Types::Value)
|
37
|
+
# deprecated behavior using a bespoke api
|
38
|
+
type.coerce(fetch(field, default))
|
39
|
+
else
|
40
|
+
# newer behavior better aligned with ActiveModel::Type
|
41
|
+
instance = Blacklight::Types.lookup(type, **kwargs) if type.is_a? Symbol
|
42
|
+
instance ||= type.new(**kwargs)
|
43
|
+
|
44
|
+
instance.cast(fetch(field, default))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -21,6 +21,7 @@ module Blacklight::Document
|
|
21
21
|
include Blacklight::Document::SemanticFields
|
22
22
|
include Blacklight::Document::CacheKey
|
23
23
|
include Blacklight::Document::Export
|
24
|
+
include Blacklight::Document::Attributes
|
24
25
|
|
25
26
|
included do
|
26
27
|
extend ActiveModel::Naming
|
@@ -70,13 +71,20 @@ module Blacklight::Document
|
|
70
71
|
alias has_field? has?
|
71
72
|
alias has_key? key?
|
72
73
|
|
73
|
-
|
74
|
+
NO_DEFAULT_PROVIDED = Object.new # :nodoc:
|
75
|
+
def fetch key, default = NO_DEFAULT_PROVIDED
|
74
76
|
if key? key
|
75
77
|
self[key]
|
76
|
-
elsif
|
77
|
-
|
78
|
+
elsif block_given?
|
79
|
+
yield(self) if block_given?
|
80
|
+
elsif default != NO_DEFAULT_PROVIDED
|
81
|
+
if default.respond_to?(:call)
|
82
|
+
default.call(self)
|
83
|
+
else
|
84
|
+
default
|
85
|
+
end
|
78
86
|
else
|
79
|
-
|
87
|
+
raise KeyError, "key not found \"#{key}\""
|
80
88
|
end
|
81
89
|
end
|
82
90
|
|
@@ -116,21 +124,5 @@ module Blacklight::Document
|
|
116
124
|
def unique_key
|
117
125
|
@unique_key ||= 'id'
|
118
126
|
end
|
119
|
-
|
120
|
-
# Define an attribute reader on a document model
|
121
|
-
# @example
|
122
|
-
# class SolrDocument
|
123
|
-
# include Blacklight::Solr::Document
|
124
|
-
# attribute :title, Blacklight::Types::String, 'title_tesim'
|
125
|
-
# end
|
126
|
-
#
|
127
|
-
# doc = SolrDocument.new(title_tesim: ["One flew over the cuckoo's nest"])
|
128
|
-
# doc.title
|
129
|
-
# #=> "One flew over the cuckoo's nest"
|
130
|
-
def attribute(name, type, field)
|
131
|
-
define_method name do
|
132
|
-
type.coerce(self[field])
|
133
|
-
end
|
134
|
-
end
|
135
127
|
end
|
136
128
|
end
|
data/app/models/search.rb
CHANGED
@@ -4,7 +4,12 @@ class Search < ApplicationRecord
|
|
4
4
|
belongs_to :user, optional: true
|
5
5
|
|
6
6
|
# use a backwards-compatible serializer until the Rails API stabilizes and we can evaluate for major-revision compatibility
|
7
|
-
|
7
|
+
if ::Rails.version.to_f >= 7.1
|
8
|
+
# non-deprecated coder: keyword arg for Rails 7.1+
|
9
|
+
serialize :query_params, coder: Blacklight::SearchParamsYamlCoder
|
10
|
+
else
|
11
|
+
serialize :query_params, Blacklight::SearchParamsYamlCoder
|
12
|
+
end
|
8
13
|
|
9
14
|
# A Search instance is considered a saved search if it has a user_id.
|
10
15
|
def saved?
|
@@ -5,7 +5,7 @@ module Blacklight
|
|
5
5
|
class Join < AbstractStep
|
6
6
|
def render
|
7
7
|
options = config.separator_options || {}
|
8
|
-
next_step(values.map { |x| html_escape(x) }.to_sentence(options).html_safe)
|
8
|
+
next_step(values.map { |x| x.html_safe? ? x : html_escape(x) }.to_sentence(options).html_safe)
|
9
9
|
end
|
10
10
|
|
11
11
|
private
|
@@ -22,17 +22,19 @@ module Blacklight
|
|
22
22
|
|
23
23
|
# @return [Array]
|
24
24
|
def fetch
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
25
|
+
if field_config.highlight
|
26
|
+
value = retrieve_highlight
|
27
|
+
end
|
28
|
+
if value.blank?
|
29
|
+
value = if field_config.accessor
|
30
|
+
retieve_using_accessor
|
31
|
+
elsif field_config.values
|
32
|
+
retrieve_values
|
33
|
+
else
|
34
|
+
retrieve_simple
|
35
|
+
end
|
36
|
+
end
|
37
|
+
Array.wrap(value)
|
36
38
|
end
|
37
39
|
|
38
40
|
private
|
@@ -1,31 +1,119 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_model"
|
4
|
+
|
3
5
|
module Blacklight
|
4
6
|
# These are data types that blacklight can use to coerce values from the index
|
5
7
|
module Types
|
6
|
-
|
8
|
+
@registry = ActiveModel::Type::Registry.new
|
9
|
+
|
10
|
+
class << self
|
11
|
+
delegate :lookup, :register, to: :@registry
|
12
|
+
end
|
13
|
+
|
14
|
+
class Value
|
7
15
|
def self.coerce(input)
|
8
|
-
|
16
|
+
new.cast(input)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(**kwargs)
|
20
|
+
@kwargs = kwargs
|
21
|
+
end
|
22
|
+
|
23
|
+
def cast(input)
|
24
|
+
if input.is_a?(::Array)
|
25
|
+
input.first
|
26
|
+
else
|
27
|
+
input
|
28
|
+
end
|
9
29
|
end
|
10
30
|
end
|
11
31
|
|
12
|
-
class
|
13
|
-
def
|
14
|
-
|
32
|
+
class Array < Value
|
33
|
+
def initialize(of: nil, **kwargs)
|
34
|
+
@of = of
|
35
|
+
@kwargs = kwargs
|
36
|
+
end
|
37
|
+
|
38
|
+
def cast(input)
|
39
|
+
::Array.wrap(input).map do |value|
|
40
|
+
lookup_type.cast(value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def lookup_type
|
47
|
+
return Blacklight::Types::Value.new(**@kwargs) if @of.nil?
|
48
|
+
|
49
|
+
@lookup_type ||= Blacklight::Types.lookup(@of, **@kwargs)
|
15
50
|
end
|
16
51
|
end
|
17
52
|
|
18
|
-
class
|
19
|
-
def
|
20
|
-
|
21
|
-
|
53
|
+
class String < Value
|
54
|
+
def cast(input)
|
55
|
+
super&.to_s
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class Date < Value
|
60
|
+
def cast(input)
|
61
|
+
value = super
|
62
|
+
return if value.blank?
|
22
63
|
|
23
64
|
begin
|
24
|
-
::Date.parse(
|
65
|
+
::Date.parse(value.to_s)
|
25
66
|
rescue ArgumentError
|
26
|
-
Rails.logger&.info "Unable to parse date: #{
|
67
|
+
Rails.logger&.info "Unable to parse date: #{value.inspect}"
|
27
68
|
end
|
28
69
|
end
|
29
70
|
end
|
71
|
+
|
72
|
+
class Boolean < Value
|
73
|
+
def cast(input)
|
74
|
+
ActiveModel::Type::Boolean.new.cast(super)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class JsonValue < Value
|
79
|
+
def cast(input)
|
80
|
+
value = super
|
81
|
+
|
82
|
+
return value unless value.is_a?(String)
|
83
|
+
|
84
|
+
JSON.parse(value)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Selector < Array
|
89
|
+
def initialize(by: nil, block: nil, **kwargs)
|
90
|
+
super(**kwargs)
|
91
|
+
@by = by
|
92
|
+
@block = block
|
93
|
+
end
|
94
|
+
|
95
|
+
def cast(input)
|
96
|
+
return super.public_send(@by) unless @block
|
97
|
+
|
98
|
+
super.public_send(@by, &@block)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# rubocop:disable Rails/OutputSafety
|
103
|
+
class Html < String
|
104
|
+
def cast(input)
|
105
|
+
super&.html_safe
|
106
|
+
end
|
107
|
+
end
|
108
|
+
# rubocop:enable Rails/OutputSafety
|
109
|
+
|
110
|
+
register :boolean, Boolean
|
111
|
+
register :string, String
|
112
|
+
register :date, Date
|
113
|
+
register :array, Array
|
114
|
+
register :json, JsonValue
|
115
|
+
register :html, Html
|
116
|
+
register :select, Selector
|
117
|
+
register :value, Value
|
30
118
|
end
|
31
119
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% # container for a single doc -%>
|
2
2
|
<% view_config = local_assigns[:view_config] || blacklight_config.view_config(document_index_view_type) %>
|
3
3
|
<%= render (view_config.document_component || Blacklight::DocumentComponent).new(presenter: document_presenter(document), counter: document_counter_with_offset(document_counter)) do |component| %>
|
4
|
-
<% component.public_send(view_config.document_component.blank? && view_config.partials.any? ? :
|
4
|
+
<% component.public_send(view_config.document_component.blank? && view_config.partials.any? ? :with_body : :with_partial) do %>
|
5
5
|
<%= render_document_partials document, view_config.partials, component: component, document_counter: document_counter %>
|
6
6
|
<% end %>
|
7
7
|
<% end %>
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<%= render(Blacklight::FacetFieldComponent.new(facet_field: facet_field_presenter(facet_field, nil))) do |component| %>
|
2
|
-
<% component.
|
2
|
+
<% component.with_label do %>
|
3
3
|
<%= facet_field_label(facet_field.key) %>
|
4
4
|
<% end %>
|
5
|
-
<% component.
|
5
|
+
<% component.with_body do %>
|
6
6
|
<%= yield %>
|
7
7
|
<% end %>
|
8
8
|
<% end %>
|
@@ -4,4 +4,4 @@
|
|
4
4
|
advanced_search_url: search_action_url(action: 'advanced_search'),
|
5
5
|
params: search_state.params_for_search.except(:qt),
|
6
6
|
search_fields: Deprecation.silence(Blacklight::ConfigurationHelperBehavior) { search_fields },
|
7
|
-
autocomplete_path:
|
7
|
+
autocomplete_path: suggest_index_catalog_path)) %>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<% content_for(:head) { render_link_rel_alternates } %>
|
5
5
|
|
6
6
|
<%= render (blacklight_config.view_config(:show).document_component || Blacklight::DocumentComponent).new(presenter: document_presenter(@document), component: :div, title_component: :h1, show: true) do |component| %>
|
7
|
-
<% component.
|
7
|
+
<% component.with_footer do %>
|
8
8
|
<% if @document.respond_to?(:export_as_openurl_ctx_kev) %>
|
9
9
|
<!--
|
10
10
|
// COinS, for Zotero among others.
|
@@ -17,7 +17,7 @@
|
|
17
17
|
|
18
18
|
<%# Use :body for complete backwards compatibility (overriding the component body markup),
|
19
19
|
but if the app explicitly opted-in to components, make the partials data available as :partials to ease migrations pain %>
|
20
|
-
<% component.public_send(blacklight_config.view_config(:show).document_component.blank? && blacklight_config.view_config(:show).partials.any? ? :
|
20
|
+
<% component.public_send(blacklight_config.view_config(:show).document_component.blank? && blacklight_config.view_config(:show).partials.any? ? :with_body : :with_partial) do %>
|
21
21
|
<div id="doc_<%= @document.id.to_s.parameterize %>">
|
22
22
|
<%= render_document_partials @document, blacklight_config.view_config(:show).partials, component: component %>
|
23
23
|
</div>
|
@@ -1,2 +1,2 @@
|
|
1
|
-
<%= render 'show_tools' %>
|
1
|
+
<%= render 'show_tools', document: document %>
|
2
2
|
<%= render(Blacklight::Document::MoreLikeThisComponent.new(document: document)) %>
|
@@ -1,14 +1,15 @@
|
|
1
|
-
<% if
|
1
|
+
<% document = @document if local_assigns[:document].nil? %>
|
2
|
+
<% if show_doc_actions? document %>
|
2
3
|
<div class="card show-tools">
|
3
4
|
<div class="card-header">
|
4
5
|
<h2 class="mb-0 h6"><%= t('blacklight.tools.title') %></h2>
|
5
6
|
</div>
|
6
7
|
<% if render_show_doc_actions_method_from_blacklight? %>
|
7
|
-
<%= render(Blacklight::Document::ActionsComponent.new(document:
|
8
|
+
<%= render(Blacklight::Document::ActionsComponent.new(document: document, tag: 'ul', classes: 'list-group list-group-flush', wrapping_tag: 'li', wrapping_classes: 'list-group-item', actions: document_actions(document), url_opts: Blacklight::Parameters.sanitize(params.to_unsafe_h))) %>
|
8
9
|
<% else %>
|
9
10
|
<% Deprecation.warn(self, '#render_show_doc_actions is deprecated; use ActionComponents instead') %>
|
10
11
|
<ul class="list-group list-group-flush">
|
11
|
-
<%= render_show_doc_actions
|
12
|
+
<%= render_show_doc_actions document do |config, inner| %>
|
12
13
|
<li class="list-group-item <%= config.key %>">
|
13
14
|
<%= inner %>
|
14
15
|
</li>
|
@@ -1,11 +1,11 @@
|
|
1
1
|
<%= render Blacklight::System::ModalComponent.new do |component| %>
|
2
|
-
<% component.
|
2
|
+
<% component.with_prefix do %>
|
3
3
|
<div class="facet-pagination top row justify-content-between">
|
4
4
|
<%= render :partial=>'facet_pagination' %>
|
5
5
|
</div>
|
6
6
|
<% end %>
|
7
7
|
|
8
|
-
<% component.
|
8
|
+
<% component.with_title { facet_field_label(@facet.key) } %>
|
9
9
|
|
10
10
|
<%= render partial: 'facet_index_navigation' if @facet.index_range && @display_facet.index? %>
|
11
11
|
|
@@ -13,7 +13,7 @@
|
|
13
13
|
<%= render_facet_limit(@display_facet, layout: false) %>
|
14
14
|
</div>
|
15
15
|
|
16
|
-
<% component.
|
16
|
+
<% component.with_footer do %>
|
17
17
|
<div class="facet-pagination bottom row justify-content-between">
|
18
18
|
<%= render :partial=>'facet_pagination' %>
|
19
19
|
</div>
|
@@ -28,15 +28,15 @@
|
|
28
28
|
</nav>
|
29
29
|
<%= render partial: 'shared/header_navbar' %>
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
<main id="main-container" class="<%= container_classes %>" role="main" aria-label="<%= t('blacklight.main.aria.main_container') %>">
|
32
|
+
<%= content_for(:container_header) %>
|
33
33
|
|
34
|
-
|
34
|
+
<%= render partial: 'shared/flash_msg', layout: 'shared/flash_messages' %>
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
<div class="row">
|
37
|
+
<%= content_for?(:content) ? yield(:content) : yield %>
|
38
|
+
</div>
|
39
|
+
</main>
|
40
40
|
|
41
41
|
<%= render partial: 'shared/footer' %>
|
42
42
|
<%= render partial: 'shared/modal' %>
|
@@ -1,22 +1 @@
|
|
1
|
-
|
2
|
-
<div class="<%= container_classes %>">
|
3
|
-
<%= link_to application_name, root_path, class: 'mb-0 navbar-brand navbar-logo' %>
|
4
|
-
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-bs-toggle="collapse" data-target="#user-util-collapse" data-bs-target="#user-util-collapse" aria-controls="user-util-collapse" aria-expanded="false" aria-label="Toggle navigation">
|
5
|
-
<span class="navbar-toggler-icon"></span>
|
6
|
-
</button>
|
7
|
-
|
8
|
-
<div class="collapse navbar-collapse justify-content-md-end" id="user-util-collapse">
|
9
|
-
<%= render 'shared/user_util_links' %>
|
10
|
-
</div>
|
11
|
-
</div>
|
12
|
-
</nav>
|
13
|
-
|
14
|
-
<%= content_tag :div, class: 'navbar-search navbar navbar-light bg-light', role: 'navigation', aria: { label: t('blacklight.search.header') } do %>
|
15
|
-
<div class="<%= container_classes %>">
|
16
|
-
<%= render((blacklight_config&.view_config(document_index_view_type)&.search_bar_component ||Blacklight::SearchBarComponent).new(
|
17
|
-
url: search_action_url,
|
18
|
-
advanced_search_url: search_action_url(action: 'advanced_search'),
|
19
|
-
params: search_state.params_for_search.except(:qt),
|
20
|
-
autocomplete_path: search_action_path(action: :suggest))) %>
|
21
|
-
</div>
|
22
|
-
<% end %>
|
1
|
+
<%= render blacklight_config.header_component.new(blacklight_config: blacklight_config) %>
|
data/blacklight.gemspec
CHANGED
@@ -25,22 +25,21 @@ Gem::Specification.new do |s|
|
|
25
25
|
|
26
26
|
s.required_ruby_version = '>= 2.5'
|
27
27
|
|
28
|
-
s.add_dependency "rails", '>= 5.1', '< 7.
|
28
|
+
s.add_dependency "rails", '>= 5.1', '< 7.2'
|
29
29
|
s.add_dependency "globalid"
|
30
30
|
s.add_dependency "jbuilder", '~> 2.7'
|
31
31
|
s.add_dependency "kaminari", ">= 0.15" # the pagination (page 1,2,3, etc..) of our search results
|
32
32
|
s.add_dependency "deprecation"
|
33
33
|
s.add_dependency "i18n", '>= 1.7.0' # added named parameters
|
34
34
|
s.add_dependency "ostruct", '>= 0.3.2'
|
35
|
-
s.add_dependency "view_component", '
|
35
|
+
s.add_dependency "view_component", '>= 2.66', '< 4'
|
36
36
|
s.add_dependency 'hashdiff'
|
37
37
|
|
38
38
|
s.add_development_dependency "rsolr", ">= 1.0.6", "< 3" # Library for interacting with rSolr.
|
39
|
-
s.add_development_dependency "rspec-rails", "
|
39
|
+
s.add_development_dependency "rspec-rails", ">= 5.0" # some versions tested need >= 6.0
|
40
40
|
s.add_development_dependency "rspec-collection_matchers", ">= 1.0"
|
41
41
|
s.add_development_dependency 'axe-core-rspec'
|
42
42
|
s.add_development_dependency "capybara", '~> 3'
|
43
|
-
s.add_development_dependency 'webdrivers'
|
44
43
|
s.add_development_dependency 'selenium-webdriver'
|
45
44
|
s.add_development_dependency 'engine_cart', '~> 2.1'
|
46
45
|
s.add_development_dependency "equivalent-xml"
|
data/docker-compose.yml
CHANGED
@@ -17,6 +17,7 @@ services:
|
|
17
17
|
environment:
|
18
18
|
- SOLR_URL # Set via environment variable or use default defined in .env file
|
19
19
|
- RAILS_VERSION # Set via environment variable or use default defined in .env file
|
20
|
+
- VIEW_COMPONENT_VERSION # Set via environment variable or use default defined in .env file
|
20
21
|
- SOLR_ENV=docker-compose
|
21
22
|
- ENGINE_CART_RAILS_OPTIONS=--skip-git --skip-listen --skip-spring --skip-keeps --skip-action-cable --skip-coffee --skip-test --skip-solr
|
22
23
|
|
@@ -20,16 +20,42 @@ module Blacklight
|
|
20
20
|
autoload :ShowField
|
21
21
|
end
|
22
22
|
|
23
|
+
class_attribute :default_values, default: {}
|
24
|
+
|
23
25
|
# Set up Blacklight::Configuration.default_values to contain the basic, required Blacklight fields
|
24
26
|
class << self
|
25
27
|
def property(key, default: nil)
|
26
28
|
default_values[key] = default
|
27
29
|
end
|
28
30
|
|
29
|
-
def
|
30
|
-
@
|
31
|
+
def default_configuration(&block)
|
32
|
+
@default_configurations ||= []
|
33
|
+
|
34
|
+
if block
|
35
|
+
@default_configurations << block
|
36
|
+
|
37
|
+
block.call if @default_configuration_initialized
|
38
|
+
end
|
39
|
+
|
40
|
+
@default_configurations
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize_default_configuration
|
44
|
+
@default_configurations&.map(&:call)
|
45
|
+
@default_configuration_initialized = true
|
31
46
|
end
|
47
|
+
|
48
|
+
def initialized_default_configuration?
|
49
|
+
@default_configuration_initialized
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
property :logo_link
|
54
|
+
property :header_component, default: nil
|
55
|
+
def header_component
|
56
|
+
super || Blacklight::HeaderComponent
|
32
57
|
end
|
58
|
+
|
33
59
|
# === Search request configuration
|
34
60
|
|
35
61
|
# @!attribute http_method
|
@@ -52,6 +78,10 @@ module Blacklight
|
|
52
78
|
# @since v5.2.0
|
53
79
|
# @return [String] The url path (relative to the solr base url) to use when requesting only a single document
|
54
80
|
property :document_solr_path, default: 'get'
|
81
|
+
# @!attribute json_solr_path
|
82
|
+
# @since v7.34.0
|
83
|
+
# @return [String] The url path (relative to the solr base url) to use when using Solr's JSON Query DSL (as with the advanced search)
|
84
|
+
property :json_solr_path, default: nil
|
55
85
|
# @!attribute document_unique_id_param
|
56
86
|
# @since v5.2.0
|
57
87
|
# @return [Symbol] The solr query parameter used for sending the unique identifiers for one or more documents
|
@@ -357,6 +387,8 @@ module Blacklight
|
|
357
387
|
define_field_access :email_field, Blacklight::Configuration::DisplayField
|
358
388
|
|
359
389
|
def initialize(hash = {})
|
390
|
+
self.class.initialize_default_configuration unless self.class.initialized_default_configuration?
|
391
|
+
|
360
392
|
super(self.class.default_values.deep_dup.merge(hash))
|
361
393
|
yield(self) if block_given?
|
362
394
|
|
@@ -368,6 +400,11 @@ module Blacklight
|
|
368
400
|
repository_class.new(self)
|
369
401
|
end
|
370
402
|
|
403
|
+
# @return [String] The destination for the link around the logo in the header
|
404
|
+
def logo_link
|
405
|
+
super || Rails.application.routes.url_helpers.root_path
|
406
|
+
end
|
407
|
+
|
371
408
|
# DSL helper
|
372
409
|
# @yield [config]
|
373
410
|
# @yieldparam [Blacklight::Configuration]
|
data/lib/blacklight/engine.rb
CHANGED
@@ -6,6 +6,17 @@ module Blacklight
|
|
6
6
|
class Engine < Rails::Engine
|
7
7
|
engine_name "blacklight"
|
8
8
|
|
9
|
+
config.before_configuration do
|
10
|
+
# see https://github.com/fxn/zeitwerk#for_gem
|
11
|
+
# Blacklight puts a generator into LOCAL APP lib/generators, so tell
|
12
|
+
# zeitwerk to ignore the whole directory? If we're using zeitwerk
|
13
|
+
#
|
14
|
+
# https://github.com/cbeer/engine_cart/issues/117
|
15
|
+
if Rails.try(:autoloaders).try(:main).respond_to?(:ignore)
|
16
|
+
Rails.autoloaders.main.ignore(Rails.root.join('lib/generators'))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
9
20
|
# BlacklightHelper is needed by all helpers, so we inject it
|
10
21
|
# into action view base here.
|
11
22
|
initializer 'blacklight.helpers' do
|
@@ -14,6 +25,10 @@ module Blacklight
|
|
14
25
|
end
|
15
26
|
end
|
16
27
|
|
28
|
+
config.after_initialize do
|
29
|
+
Blacklight::Configuration.initialize_default_configuration
|
30
|
+
end
|
31
|
+
|
17
32
|
# This makes our rake tasks visible.
|
18
33
|
rake_tasks do
|
19
34
|
Dir.chdir(File.expand_path(File.join(File.dirname(__FILE__), '..'))) do
|
@@ -20,7 +20,7 @@ module Blacklight::Solr
|
|
20
20
|
# Execute a search query against solr
|
21
21
|
# @param [Hash] params solr query parameters
|
22
22
|
def search params = {}
|
23
|
-
send_and_receive
|
23
|
+
send_and_receive search_path(params), params.reverse_merge(qt: blacklight_config.qt)
|
24
24
|
end
|
25
25
|
|
26
26
|
# @param [Hash] request_params
|
@@ -77,7 +77,7 @@ module Blacklight::Solr
|
|
77
77
|
# @return [Hash]
|
78
78
|
# @!visibility private
|
79
79
|
def build_solr_request(solr_params)
|
80
|
-
if solr_params
|
80
|
+
if uses_json_query_dsl?(solr_params)
|
81
81
|
{
|
82
82
|
data: { params: solr_params.to_hash.except(:json) }.merge(solr_params[:json]).to_json,
|
83
83
|
method: :post,
|
@@ -121,5 +121,17 @@ module Blacklight::Solr
|
|
121
121
|
[]
|
122
122
|
end
|
123
123
|
end
|
124
|
+
|
125
|
+
# @return [String]
|
126
|
+
def search_path(solr_params)
|
127
|
+
return blacklight_config.json_solr_path if blacklight_config.json_solr_path && uses_json_query_dsl?(solr_params)
|
128
|
+
|
129
|
+
blacklight_config.solr_path
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [Boolean]
|
133
|
+
def uses_json_query_dsl?(solr_params)
|
134
|
+
solr_params[:json].present?
|
135
|
+
end
|
124
136
|
end
|
125
137
|
end
|