blacklight 9.0.0.beta1 → 9.0.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. data/.github/matrix.json +47 -0
  3. data/.github/workflows/build.yml +16 -0
  4. data/.github/workflows/lint.yml +25 -0
  5. data/.github/workflows/main.yml +22 -0
  6. data/.github/workflows/release_7_x_scheduled.yml +39 -0
  7. data/.github/workflows/release_8_x_scheduled.yml +39 -0
  8. data/.github/workflows/test.yml +53 -0
  9. data/.rubocop.yml +70 -2
  10. data/.rubocop_todo.yml +43 -67
  11. data/.solr_wrapper.yml +2 -0
  12. data/VERSION +1 -1
  13. data/app/assets/builds/blacklight.css +19 -15
  14. data/app/assets/javascripts/blacklight/blacklight.esm.js +31 -69
  15. data/app/assets/javascripts/blacklight/blacklight.esm.js.map +1 -1
  16. data/app/assets/javascripts/blacklight/blacklight.js +31 -69
  17. data/app/assets/javascripts/blacklight/blacklight.js.map +1 -1
  18. data/app/assets/stylesheets/blacklight/_bootstrap_overrides.scss +4 -0
  19. data/app/assets/stylesheets/blacklight/_facets.scss +2 -2
  20. data/app/assets/stylesheets/blacklight/_header.scss +4 -0
  21. data/app/assets/stylesheets/blacklight/_modal.scss +9 -8
  22. data/app/assets/stylesheets/blacklight/_pagination.scss +1 -3
  23. data/app/assets/stylesheets/blacklight/_search_history.scss +0 -4
  24. data/app/assets/stylesheets/blacklight/blacklight_defaults.scss +3 -0
  25. data/app/components/blacklight/advanced_search_form_component.rb +2 -2
  26. data/app/components/blacklight/constraints_component.rb +2 -2
  27. data/app/components/blacklight/document/action_component.rb +1 -3
  28. data/app/components/blacklight/document/bookmark_component.rb +2 -2
  29. data/app/components/blacklight/document/more_like_this_component.rb +2 -2
  30. data/app/components/blacklight/document/page_header_component.rb +2 -2
  31. data/app/components/blacklight/document/thumbnail_component.html.erb +3 -7
  32. data/app/components/blacklight/document/thumbnail_component.rb +7 -6
  33. data/app/components/blacklight/document_component.rb +3 -3
  34. data/app/components/blacklight/document_title_component.rb +3 -10
  35. data/app/components/blacklight/facet_field_checkboxes_component.rb +2 -20
  36. data/app/components/blacklight/facet_field_component.rb +2 -17
  37. data/app/components/blacklight/facet_field_filter_component.rb +2 -21
  38. data/app/components/blacklight/facet_field_inclusive_constraint_component.rb +4 -25
  39. data/app/components/blacklight/facet_field_list_component.rb +2 -32
  40. data/app/components/blacklight/facet_field_no_layout_component.rb +2 -10
  41. data/app/components/blacklight/facet_field_pagination_component.html.erb +2 -2
  42. data/app/components/blacklight/facet_item_component.rb +2 -74
  43. data/app/components/blacklight/facet_item_pivot_component.rb +1 -1
  44. data/app/components/blacklight/facets/checkboxes_component.rb +26 -0
  45. data/app/components/blacklight/facets/count_component.rb +23 -0
  46. data/app/components/blacklight/{facet_field_component.html.erb → facets/field_component.html.erb} +1 -1
  47. data/app/components/blacklight/facets/field_component.rb +23 -0
  48. data/app/components/blacklight/facets/filters_component.html.erb +4 -0
  49. data/app/components/blacklight/facets/filters_component.rb +27 -0
  50. data/app/components/blacklight/{facet_field_inclusive_constraint_component.html.erb → facets/inclusive_constraint_component.html.erb} +1 -1
  51. data/app/components/blacklight/facets/inclusive_constraint_component.rb +31 -0
  52. data/app/components/blacklight/{facet_field_filter_component.html.erb → facets/index_navigation_component.html.erb} +1 -1
  53. data/app/components/blacklight/facets/index_navigation_component.rb +32 -0
  54. data/app/components/blacklight/facets/item_component.rb +73 -0
  55. data/app/components/blacklight/facets/list_component.html.erb +11 -0
  56. data/app/components/blacklight/facets/list_component.rb +38 -0
  57. data/app/components/blacklight/facets/no_layout_component.rb +16 -0
  58. data/app/components/blacklight/facets/selected_value_component.rb +29 -0
  59. data/app/components/blacklight/facets/suggest_component.html.erb +12 -0
  60. data/app/components/blacklight/facets/suggest_component.rb +22 -0
  61. data/app/components/blacklight/metadata_field_plain_text_layout_component.rb +2 -2
  62. data/app/components/blacklight/response/facet_group_component.html.erb +1 -1
  63. data/app/components/blacklight/response/facet_group_component.rb +5 -1
  64. data/app/components/blacklight/system/dropdown_component.html.erb +1 -1
  65. data/app/components/blacklight/system/dropdown_component.rb +1 -1
  66. data/app/components/blacklight/top_navbar_component.html.erb +1 -1
  67. data/app/controllers/concerns/blacklight/bookmarks.rb +3 -3
  68. data/app/controllers/concerns/blacklight/catalog.rb +10 -25
  69. data/app/controllers/concerns/blacklight/controller.rb +1 -1
  70. data/app/controllers/concerns/blacklight/facetable.rb +34 -0
  71. data/app/controllers/concerns/blacklight/search_context.rb +1 -1
  72. data/app/controllers/concerns/blacklight/searchable.rb +1 -1
  73. data/app/helpers/blacklight/configuration_helper_behavior.rb +2 -2
  74. data/app/helpers/blacklight/document_helper_behavior.rb +3 -1
  75. data/app/helpers/blacklight/facets_helper_behavior.rb +9 -0
  76. data/app/helpers/blacklight/icon_helper_behavior.rb +2 -2
  77. data/app/javascript/blacklight-frontend/checkbox_submit.js +3 -0
  78. data/app/javascript/blacklight-frontend/debounce.js +1 -1
  79. data/app/javascript/blacklight-frontend/facet_suggest.js +23 -3
  80. data/app/javascript/blacklight-frontend/index.js +0 -2
  81. data/app/javascript/blacklight-frontend/modal.js +1 -4
  82. data/app/javascript/blacklight-frontend/search_context.js +3 -2
  83. data/app/models/facet_search_builder.rb +5 -0
  84. data/app/presenters/blacklight/facet_field_presenter.rb +1 -1
  85. data/app/presenters/blacklight/json_presenter.rb +1 -3
  86. data/app/presenters/blacklight/rendering/helper_method.rb +4 -4
  87. data/app/presenters/blacklight/rendering/join.rb +2 -2
  88. data/app/services/blacklight/facet_search_service.rb +44 -0
  89. data/app/services/blacklight/field_retriever.rb +1 -1
  90. data/app/services/blacklight/search_service.rb +6 -6
  91. data/app/values/blacklight/types.rb +2 -2
  92. data/app/views/catalog/_facet_pivot.html.erb +1 -1
  93. data/app/views/catalog/_home_text.html.erb +2 -2
  94. data/app/views/catalog/_sort_and_per_page.html.erb +1 -1
  95. data/app/views/catalog/facet.html.erb +8 -10
  96. data/config/locales/blacklight.ar.yml +2 -2
  97. data/config/locales/blacklight.es.yml +2 -2
  98. data/config/locales/blacklight.fr.yml +2 -2
  99. data/config/locales/blacklight.hu.yml +2 -2
  100. data/config/locales/blacklight.it.yml +2 -2
  101. data/config/locales/blacklight.nl.yml +1 -1
  102. data/config/locales/blacklight.pt-BR.yml +2 -2
  103. data/config/locales/blacklight.sq.yml +2 -2
  104. data/config/locales/blacklight.zh.yml +2 -2
  105. data/lib/blacklight/abstract_repository.rb +2 -2
  106. data/lib/blacklight/abstract_search_builder.rb +154 -0
  107. data/lib/blacklight/configuration/context.rb +3 -3
  108. data/lib/blacklight/configuration/facet_field.rb +6 -6
  109. data/lib/blacklight/configuration/field.rb +4 -4
  110. data/lib/blacklight/configuration/fields.rb +0 -1
  111. data/lib/blacklight/configuration/search_field.rb +1 -1
  112. data/lib/blacklight/configuration/view_config.rb +2 -2
  113. data/lib/blacklight/configuration.rb +6 -7
  114. data/lib/blacklight/facet_search_builder.rb +18 -0
  115. data/lib/blacklight/nested_open_struct_with_hash_access.rb +1 -1
  116. data/lib/blacklight/open_struct_with_hash_access.rb +2 -2
  117. data/lib/blacklight/search_builder.rb +1 -159
  118. data/lib/blacklight/search_state/filter_field.rb +4 -4
  119. data/lib/blacklight/search_state/pivot_filter_field.rb +4 -4
  120. data/lib/blacklight/solr/abstract_filter_query_builder.rb +77 -0
  121. data/lib/blacklight/solr/default_filter_query_builder.rb +20 -0
  122. data/lib/blacklight/solr/facet_search_builder_behavior.rb +62 -0
  123. data/lib/blacklight/solr/repository.rb +8 -9
  124. data/lib/blacklight/solr/response/facets.rb +2 -2
  125. data/lib/blacklight/solr/response/params.rb +0 -4
  126. data/lib/blacklight/solr/response.rb +5 -1
  127. data/lib/blacklight/solr/search_builder_behavior.rb +17 -132
  128. data/lib/blacklight.rb +1 -1
  129. data/lib/generators/blacklight/assets/importmap_generator.rb +3 -5
  130. data/lib/generators/blacklight/assets_generator.rb +1 -1
  131. data/lib/generators/blacklight/search_builder_generator.rb +1 -1
  132. data/lib/generators/blacklight/templates/.solr_wrapper.yml +2 -0
  133. data/lib/generators/blacklight/templates/catalog_controller.rb +3 -1
  134. data/lib/generators/blacklight/templates/solr/conf/solrconfig.xml +0 -4
  135. data/package.json +3 -3
  136. data/spec/components/blacklight/advanced_search_form_component_spec.rb +18 -22
  137. data/spec/components/blacklight/constraint_layout_component_spec.rb +8 -8
  138. data/spec/components/blacklight/constraints_component_spec.rb +11 -11
  139. data/spec/components/blacklight/document/action_component_spec.rb +23 -15
  140. data/spec/components/blacklight/document/group_component_spec.rb +10 -15
  141. data/spec/components/blacklight/document/page_header_component_spec.rb +35 -28
  142. data/spec/components/blacklight/document/sidebar_component_spec.rb +5 -11
  143. data/spec/components/blacklight/document_component_spec.rb +98 -65
  144. data/spec/components/blacklight/facet_component_spec.rb +12 -8
  145. data/spec/components/blacklight/facet_item_pivot_component_spec.rb +12 -12
  146. data/spec/components/blacklight/{facet_field_checkboxes_component_spec.rb → facets/checkboxes_component_spec.rb} +13 -13
  147. data/spec/components/blacklight/facets/filters_component_spec.rb +36 -0
  148. data/spec/components/blacklight/facets/index_navigation_component_spec.rb +40 -0
  149. data/spec/components/blacklight/{facet_item_component_spec.rb → facets/item_component_spec.rb} +10 -10
  150. data/spec/components/blacklight/{facet_field_list_component_spec.rb → facets/list_component_spec.rb} +23 -23
  151. data/spec/components/blacklight/facets/suggest_component_spec.rb +68 -0
  152. data/spec/components/blacklight/header_component_spec.rb +2 -4
  153. data/spec/components/blacklight/hidden_search_state_component_spec.rb +7 -7
  154. data/spec/components/blacklight/metadata_field_component_spec.rb +17 -15
  155. data/spec/components/blacklight/response/facet_group_component_spec.rb +37 -0
  156. data/spec/components/blacklight/response/pagination_component_spec.rb +1 -1
  157. data/spec/components/blacklight/response/spellcheck_component_spec.rb +1 -1
  158. data/spec/components/blacklight/search_bar_component_spec.rb +4 -4
  159. data/spec/components/blacklight/search_context/server_applied_params_component_spec.rb +2 -2
  160. data/spec/components/blacklight/search_context/server_item_pagination_component_spec.rb +3 -5
  161. data/spec/components/blacklight/skip_link_component_spec.rb +8 -11
  162. data/spec/components/blacklight/start_over_button_component_spec.rb +4 -4
  163. data/spec/components/blacklight/system/dropdown_component_spec.rb +26 -0
  164. data/spec/components/blacklight/system/flash_message_component_spec.rb +7 -11
  165. data/spec/controllers/catalog_controller_spec.rb +12 -20
  166. data/spec/features/facets_spec.rb +70 -7
  167. data/spec/helpers/blacklight/facets_helper_behavior_spec.rb +10 -0
  168. data/spec/lib/blacklight/configuration/facet_field_spec.rb +2 -2
  169. data/spec/lib/blacklight/parameters_spec.rb +12 -1
  170. data/spec/lib/blacklight/search_state/filter_field_spec.rb +18 -0
  171. data/spec/models/blacklight/configuration_spec.rb +32 -28
  172. data/spec/models/blacklight/facet_search_builder_spec.rb +19 -0
  173. data/spec/models/blacklight/search_builder_spec.rb +1 -11
  174. data/spec/models/blacklight/solr/default_filter_query_builder_spec.rb +72 -0
  175. data/spec/models/blacklight/solr/document_spec.rb +0 -4
  176. data/spec/models/blacklight/solr/facet_search_builder_behavior_spec.rb +929 -0
  177. data/spec/models/blacklight/solr/repository_spec.rb +31 -29
  178. data/spec/models/blacklight/solr/response/facets_spec.rb +86 -40
  179. data/spec/models/blacklight/solr/response/group_response_spec.rb +8 -5
  180. data/spec/models/blacklight/solr/response/group_spec.rb +9 -5
  181. data/spec/models/blacklight/solr/response_spec.rb +96 -64
  182. data/spec/models/blacklight/solr/search_builder_behavior_spec.rb +2 -227
  183. data/spec/models/solr_document_spec.rb +5 -1
  184. data/spec/services/blacklight/search_service_spec.rb +6 -27
  185. data/spec/spec_helper.rb +0 -1
  186. data/spec/support/view_component_test_helpers.rb +0 -18
  187. data/spec/views/catalog/facet.html.erb_spec.rb +10 -3
  188. data/spec/views/catalog/index.atom.builder_spec.rb +6 -3
  189. data/spec/views/catalog/index.html.erb_spec.rb +3 -1
  190. metadata +58 -29
  191. data/.github/workflows/ruby.yml +0 -98
  192. data/app/components/blacklight/facet_field_list_component.html.erb +0 -19
  193. data/app/components/blacklight/search/facet_suggest_input.html.erb +0 -9
  194. data/app/components/blacklight/search/facet_suggest_input.rb +0 -16
  195. data/app/javascript/blacklight-frontend/modalForm.js +0 -60
  196. data/app/views/catalog/_facet_index_navigation.html.erb +0 -1
  197. data/app/views/catalog/_facet_layout.html.erb +0 -8
  198. data/app/views/catalog/_facet_pagination.html.erb +0 -1
  199. data/spec/components/blacklight/document_metadata_component_spec.rb +0 -0
  200. data/spec/components/blacklight/search/facet_suggest_input_spec.rb +0 -33
  201. data/spec/views/catalog/_facet_index_navigation.html.erb_spec.rb +0 -43
  202. data/spec/views/catalog/_facet_layout.html.erb_spec.rb +0 -41
  203. /data/app/components/blacklight/{facet_field_checkboxes_component.html.erb → facets/checkboxes_component.html.erb} +0 -0
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight::Solr
4
+ class AbstractFilterQueryBuilder
5
+ def initialize(blacklight_config:)
6
+ @blacklight_config = blacklight_config
7
+ end
8
+
9
+ attr_reader :blacklight_config
10
+
11
+ private
12
+
13
+ def facet_inclusive_value_to_fq_string(facet_field, values)
14
+ return if values.blank?
15
+
16
+ return facet_value_to_fq_string(facet_field, values.first) if values.length == 1
17
+
18
+ facet_config = blacklight_config.facet_fields[facet_field]
19
+
20
+ local_params = []
21
+ local_params << "tag=#{facet_config.tag}" if facet_config&.tag
22
+
23
+ solr_filters = values.each_with_object({}).with_index do |(v, h), index|
24
+ h["f_inclusive.#{facet_field}.#{index}"] = facet_value_to_fq_string(facet_field, v, use_local_params: false)
25
+ end
26
+
27
+ filter_query = solr_filters.keys.map do |k|
28
+ "{!query v=$#{k}}"
29
+ end.join(' OR ')
30
+
31
+ ["{!lucene#{" #{local_params.join(' ')}" unless local_params.empty?}}#{filter_query}", solr_filters]
32
+ end
33
+
34
+ ##
35
+ # Convert a facet/value pair into a solr fq parameter
36
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
37
+ def facet_value_to_fq_string(facet_field, value, use_local_params: true)
38
+ facet_config = blacklight_config.facet_fields[facet_field]
39
+
40
+ solr_field = facet_config.field if facet_config && !facet_config.query
41
+ solr_field ||= facet_field
42
+
43
+ local_params = []
44
+ local_params << "tag=#{facet_config.tag}" if use_local_params && facet_config&.tag
45
+
46
+ if facet_config&.query
47
+ if facet_config.query[value]
48
+ facet_config.query[value][:fq]
49
+ else
50
+ # exclude all documents if the custom facet key specified was not found
51
+ '-*:*'
52
+ end
53
+ elsif value.is_a?(Range)
54
+ prefix = "{!#{local_params.join(' ')}}" unless local_params.empty?
55
+ start = value.begin || '*'
56
+ finish = value.end || '*'
57
+ "#{prefix}#{solr_field}:[#{start} TO #{finish}]"
58
+ elsif value == Blacklight::SearchState::FilterField::MISSING
59
+ "-#{solr_field}:[* TO *]"
60
+ else
61
+ "{!term f=#{solr_field}#{" #{local_params.join(' ')}" unless local_params.empty?}}#{convert_to_term_value(value)}"
62
+ end
63
+ end
64
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
65
+
66
+ def convert_to_term_value(value)
67
+ case value
68
+ when DateTime, Time
69
+ value.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
70
+ when Date
71
+ value.to_time(:local).strftime("%Y-%m-%dT%H:%M:%SZ")
72
+ else
73
+ value.to_s
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight::Solr
4
+ class DefaultFilterQueryBuilder < AbstractFilterQueryBuilder
5
+ def call(filter, _solr_parameters)
6
+ filter_queries = []
7
+ all_subqueries = {}
8
+ filter.values.compact_blank.each do |value|
9
+ filter_query, subqueries = if value.is_a?(Array)
10
+ facet_inclusive_value_to_fq_string(filter.key, value.compact_blank)
11
+ else
12
+ facet_value_to_fq_string(filter.config.key, value)
13
+ end
14
+ filter_queries << filter_query
15
+ all_subqueries.merge!(subqueries) if subqueries
16
+ end
17
+ [filter_queries, all_subqueries]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight::Solr
4
+ module FacetSearchBuilderBehavior
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ include Blacklight::Solr::SearchBuilderBehavior
9
+ self.default_processor_chain = [:default_solr_parameters,
10
+ :add_search_field_default_parameters,
11
+ :add_query_to_solr,
12
+ :add_facet_fq_to_solr,
13
+ :add_facetting_to_solr,
14
+ :add_solr_fields_to_query,
15
+ :add_additional_filters,
16
+ :add_facet_paging_to_solr,
17
+ :add_facet_suggestion_parameters]
18
+ end
19
+
20
+ def add_facet_paging_to_solr(solr_params)
21
+ return if facet.blank?
22
+
23
+ facet_config = blacklight_config.facet_fields[facet]
24
+
25
+ solr_params[:rows] = 0
26
+
27
+ limit = if solr_params["facet.limit"]
28
+ solr_params["facet.limit"].to_i
29
+ else
30
+ facet_config.fetch(:more_limit, blacklight_config.default_more_limit)
31
+ end
32
+
33
+ page = search_state.facet_page
34
+ sort = search_state.facet_sort
35
+ prefix = search_state.facet_prefix
36
+ offset = (page - 1) * limit
37
+
38
+ if facet_config.json
39
+ add_solr_facet_json_params(solr_parameters, facet, facet_config, limit: limit + 1, offset: offset, sort: sort, prefix: prefix)
40
+ return
41
+ end
42
+
43
+ # Now override with our specific things for fetching facet values
44
+ facet_ex = facet_config.respond_to?(:ex) ? facet_config.ex : nil
45
+ solr_params[:'facet.field'] = with_ex_local_param(facet_ex, facet_config.field)
46
+
47
+ # Need to set as f.facet_field.facet.* to make sure we
48
+ # override any field-specific default in the solr request handler.
49
+ solr_params[:"f.#{facet_config.field}.facet.limit"] = limit + 1
50
+ solr_params[:"f.#{facet_config.field}.facet.offset"] = offset
51
+ solr_params[:"f.#{facet_config.field}.facet.sort"] = sort if sort
52
+ solr_params[:"f.#{facet_config.field}.facet.prefix"] = prefix if prefix
53
+ end
54
+
55
+ def add_facet_suggestion_parameters(solr_params)
56
+ return if facet.blank? || facet_suggestion_query.blank?
57
+
58
+ solr_params[:'facet.contains'] = facet_suggestion_query[0..50]
59
+ solr_params[:'facet.contains.ignoreCase'] = true
60
+ end
61
+ end
62
+ end
@@ -8,7 +8,6 @@ module Blacklight::Solr
8
8
  # @param [Hash] params additional solr query parameters
9
9
  def find id, params = {}
10
10
  doc_params = params.reverse_merge(blacklight_config.default_document_solr_params)
11
- .reverse_merge(qt: blacklight_config.document_solr_request_handler)
12
11
  .merge(blacklight_config.document_unique_id_param => id)
13
12
 
14
13
  solr_response = send_and_receive blacklight_config.document_solr_path || blacklight_config.solr_path, doc_params
@@ -27,7 +26,11 @@ module Blacklight::Solr
27
26
  # Execute a search query against solr
28
27
  # @param [Hash] params solr query parameters
29
28
  # @param [String] path solr request handler path
30
- def search pos_params = {}, path: nil, params: nil, **kwargs
29
+ def search pos_params = nil, path: nil, params: nil, **kwargs
30
+ if pos_params
31
+ Blacklight.deprecation.warn("Passing positional arguments to search() is deprecated. Use the params kwarg instead.")
32
+ end
33
+
31
34
  request_params = (params || pos_params).reverse_merge(kwargs).reverse_merge({ qt: blacklight_config.qt })
32
35
 
33
36
  send_and_receive(path || default_search_path(request_params), request_params)
@@ -56,15 +59,11 @@ module Blacklight::Solr
56
59
  end
57
60
 
58
61
  ##
59
- # Execute a solr query
62
+ # Execute a solr query at the given path with the parameters
60
63
  # TODO: Make this private after we have a way to abstract admin/luke and ping
61
64
  # @see [RSolr::Client#send_and_receive]
62
- # @overload find(solr_path, params)
63
- # Execute a solr query at the given path with the parameters
64
- # @param [String] solr path (defaults to blacklight_config.solr_path)
65
- # @param [Hash] parameters for RSolr::Client#send_and_receive
66
- # @overload find(params)
67
- # @param [Hash] parameters for RSolr::Client#send_and_receive
65
+ # @param [String] path solr path (defaults to blacklight_config.solr_path)
66
+ # @param [Hash, Blacklight::SearchBuilder] solr_params parameters for RSolr::Client#send_and_receive
68
67
  # @return [Blacklight::Solr::Response] the solr response object
69
68
  def send_and_receive(path, solr_params = {})
70
69
  benchmark("Solr fetch", level: :debug) do
@@ -229,7 +229,7 @@ module Blacklight::Solr::Response::Facets
229
229
 
230
230
  blacklight_config.facet_fields.select { |_k, v| v.query }.each_with_object({}) do |(field_name, facet_field), hash|
231
231
  salient_facet_queries = facet_field.query.map { |_k, x| x[:fq] }
232
- items = facet_queries.select { |k, _v| salient_facet_queries.include?(k) }.reject { |_value, hits| hits.zero? }.map do |value, hits|
232
+ items = facet_queries.slice(*salient_facet_queries).reject { |_value, hits| hits.zero? }.map do |value, hits|
233
233
  salient_fields = facet_field.query.select { |_key, val| val[:fq] == value }
234
234
  key = ((salient_fields.keys if salient_fields.respond_to? :keys) || salient_fields.first).first
235
235
  Blacklight::Solr::Response::Facets::FacetItem.new(value: key, hits: hits, label: facet_field.query[key][:label])
@@ -250,7 +250,7 @@ module Blacklight::Solr::Response::Facets
250
250
 
251
251
  salient_facet_queries = facet_field.query.map { |_k, x| x[:fq] }
252
252
 
253
- relevant_facet_data = self['facets'].select { |k, _v| salient_facet_queries.include?(k) }.reject { |_key, data| data['count'].zero? }
253
+ relevant_facet_data = self['facets'].slice(*salient_facet_queries).reject { |_key, data| data['count'].zero? }
254
254
 
255
255
  relevant_facet_data.map do |key, data|
256
256
  salient_fields = facet_field.query.select { |_key, val| val[:fq] == key }
@@ -52,10 +52,6 @@ module Blacklight::Solr::Response::Params
52
52
 
53
53
  private
54
54
 
55
- def search_builder
56
- request_params if request_params.is_a?(Blacklight::SearchBuilder)
57
- end
58
-
59
55
  # Extract JSON Request API parameters from the response header or the request itself
60
56
  def json_params
61
57
  encoded_json_params = header&.dig('params', 'json')
@@ -8,12 +8,16 @@ class Blacklight::Solr::Response < ActiveSupport::HashWithIndifferentAccess
8
8
  include MoreLikeThis
9
9
  include Params
10
10
 
11
- attr_reader :request_params
11
+ attr_reader :request_params, :search_builder
12
12
  attr_accessor :blacklight_config, :options
13
13
 
14
14
  delegate :document_factory, to: :blacklight_config
15
15
 
16
+ # @param [Hash] data
17
+ # @param [Hash, Blacklight::SearchBuilder] request_params a SearchBuilder or a Hash of parameters
16
18
  def initialize(data, request_params, options = {})
19
+ @search_builder = request_params if request_params.is_a?(Blacklight::SearchBuilder)
20
+
17
21
  super(force_to_utf8(ActiveSupport::HashWithIndifferentAccess.new(data)))
18
22
  @request_params = ActiveSupport::HashWithIndifferentAccess.new(request_params)
19
23
  self.blacklight_config = options[:blacklight_config]
@@ -10,7 +10,6 @@ module Blacklight::Solr
10
10
  :add_query_to_solr, :add_facet_fq_to_solr,
11
11
  :add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr,
12
12
  :add_sorting_to_solr, :add_group_config_to_solr,
13
- :add_facet_paging_to_solr, :add_facet_suggestion_parameters,
14
13
  :add_adv_search_clauses,
15
14
  :add_additional_filters
16
15
  ]
@@ -128,25 +127,19 @@ module Blacklight::Solr
128
127
  end
129
128
 
130
129
  search_state.filters.each do |filter|
131
- if filter.config.filter_query_builder
132
- filter_query, subqueries = filter.config.filter_query_builder.call(self, filter, solr_parameters)
133
-
134
- Array(filter_query).each do |fq|
135
- solr_parameters.append_filter_query(fq)
136
- end
137
- solr_parameters.merge!(subqueries) if subqueries
130
+ filter_query_builder_class_or_proc = filter.config.filter_query_builder || DefaultFilterQueryBuilder
131
+ if filter_query_builder_class_or_proc.is_a?(Class)
132
+ filter_query_builder = filter_query_builder_class_or_proc.new(blacklight_config: blacklight_config)
133
+ filter_query, subqueries = filter_query_builder.call(filter, solr_parameters)
138
134
  else
139
- filter.values.compact_blank.each do |value|
140
- filter_query, subqueries = if value.is_a?(Array)
141
- facet_inclusive_value_to_fq_string(filter.key, value.compact_blank)
142
- else
143
- facet_value_to_fq_string(filter.config.key, value)
144
- end
145
-
146
- solr_parameters.append_filter_query filter_query
147
- solr_parameters.merge!(subqueries) if subqueries
148
- end
135
+ # TODO: Maybe deprecate proc?
136
+ filter_query, subqueries = filter_query_builder_class_or_proc.call(self, filter, solr_parameters)
137
+ end
138
+
139
+ Array(filter_query).each do |fq|
140
+ solr_parameters.append_filter_query(fq)
149
141
  end
142
+ solr_parameters.merge!(subqueries) if subqueries
150
143
  end
151
144
  end
152
145
 
@@ -190,10 +183,8 @@ module Blacklight::Solr
190
183
  solr_parameters[:"f.#{facet.field}.facet.sort"] = facet.sort
191
184
  end
192
185
 
193
- if facet.solr_params
194
- facet.solr_params.each do |k, v|
195
- solr_parameters[:"f.#{facet.field}.#{k}"] = v
196
- end
186
+ facet.solr_params&.each do |k, v|
187
+ solr_parameters[:"f.#{facet.field}.#{k}"] = v
197
188
  end
198
189
 
199
190
  limit = facet_limit_with_pagination(field_name)
@@ -203,9 +194,9 @@ module Blacklight::Solr
203
194
 
204
195
  def add_solr_fields_to_query solr_parameters
205
196
  blacklight_config.show_fields.select(&method(:should_add_field_to_request?)).each_value do |field|
206
- field.solr_params.each do |k, v|
197
+ field.solr_params&.each do |k, v|
207
198
  solr_parameters[:"f.#{field.field}.#{k}"] = v
208
- end if field.solr_params
199
+ end
209
200
  end
210
201
 
211
202
  blacklight_config.index_fields.select(&method(:should_add_field_to_request?)).each_value do |field|
@@ -214,9 +205,9 @@ module Blacklight::Solr
214
205
  solr_parameters.append_highlight_field field.field
215
206
  end
216
207
 
217
- field.solr_params.each do |k, v|
208
+ field.solr_params&.each do |k, v|
218
209
  solr_parameters[:"f.#{field.field}.#{k}"] = v
219
- end if field.solr_params
210
+ end
220
211
  end
221
212
  end
222
213
 
@@ -242,48 +233,6 @@ module Blacklight::Solr
242
233
  solr_parameters[:group] = false if search_state.filter(grouped_key_for_results).any?
243
234
  end
244
235
 
245
- def add_facet_paging_to_solr(solr_params)
246
- return if facet.blank?
247
-
248
- facet_config = blacklight_config.facet_fields[facet]
249
-
250
- solr_params[:rows] = 0
251
-
252
- limit = if solr_params["facet.limit"]
253
- solr_params["facet.limit"].to_i
254
- else
255
- facet_config.fetch(:more_limit, blacklight_config.default_more_limit)
256
- end
257
-
258
- page = search_state.facet_page
259
- sort = search_state.facet_sort
260
- prefix = search_state.facet_prefix
261
- offset = (page - 1) * limit
262
-
263
- if facet_config.json
264
- add_solr_facet_json_params(solr_parameters, facet, facet_config, limit: limit + 1, offset: offset, sort: sort, prefix: prefix)
265
- return
266
- end
267
-
268
- # Now override with our specific things for fetching facet values
269
- facet_ex = facet_config.respond_to?(:ex) ? facet_config.ex : nil
270
- solr_params[:'facet.field'] = with_ex_local_param(facet_ex, facet_config.field)
271
-
272
- # Need to set as f.facet_field.facet.* to make sure we
273
- # override any field-specific default in the solr request handler.
274
- solr_params[:"f.#{facet_config.field}.facet.limit"] = limit + 1
275
- solr_params[:"f.#{facet_config.field}.facet.offset"] = offset
276
- solr_params[:"f.#{facet_config.field}.facet.sort"] = sort if sort
277
- solr_params[:"f.#{facet_config.field}.facet.prefix"] = prefix if prefix
278
- end
279
-
280
- def add_facet_suggestion_parameters(solr_params)
281
- return if facet.blank? || facet_suggestion_query.blank?
282
-
283
- solr_params[:'facet.contains'] = facet_suggestion_query[0..50]
284
- solr_params[:'facet.contains.ignoreCase'] = true
285
- end
286
-
287
236
  def with_ex_local_param(ex, value)
288
237
  if ex
289
238
  "{!ex=#{ex}}#{value}"
@@ -340,70 +289,6 @@ module Blacklight::Solr
340
289
 
341
290
  private
342
291
 
343
- ##
344
- # Convert a facet/value pair into a solr fq parameter
345
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
346
- def facet_value_to_fq_string(facet_field, value, use_local_params: true)
347
- facet_config = blacklight_config.facet_fields[facet_field]
348
-
349
- solr_field = facet_config.field if facet_config && !facet_config.query
350
- solr_field ||= facet_field
351
-
352
- local_params = []
353
- local_params << "tag=#{facet_config.tag}" if use_local_params && facet_config && facet_config.tag
354
-
355
- if facet_config && facet_config.query
356
- if facet_config.query[value]
357
- facet_config.query[value][:fq]
358
- else
359
- # exclude all documents if the custom facet key specified was not found
360
- '-*:*'
361
- end
362
- elsif value.is_a?(Range)
363
- prefix = "{!#{local_params.join(' ')}}" unless local_params.empty?
364
- start = value.begin || '*'
365
- finish = value.end || '*'
366
- "#{prefix}#{solr_field}:[#{start} TO #{finish}]"
367
- elsif value == Blacklight::SearchState::FilterField::MISSING
368
- "-#{solr_field}:[* TO *]"
369
- else
370
- "{!term f=#{solr_field}#{" #{local_params.join(' ')}" unless local_params.empty?}}#{convert_to_term_value(value)}"
371
- end
372
- end
373
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
374
-
375
- def facet_inclusive_value_to_fq_string(facet_field, values)
376
- return if values.blank?
377
-
378
- return facet_value_to_fq_string(facet_field, values.first) if values.length == 1
379
-
380
- facet_config = blacklight_config.facet_fields[facet_field]
381
-
382
- local_params = []
383
- local_params << "tag=#{facet_config.tag}" if facet_config && facet_config.tag
384
-
385
- solr_filters = values.each_with_object({}).with_index do |(v, h), index|
386
- h["f_inclusive.#{facet_field}.#{index}"] = facet_value_to_fq_string(facet_field, v, use_local_params: false)
387
- end
388
-
389
- filter_query = solr_filters.keys.map do |k|
390
- "{!query v=$#{k}}"
391
- end.join(' OR ')
392
-
393
- ["{!lucene#{" #{local_params.join(' ')}" unless local_params.empty?}}#{filter_query}", solr_filters]
394
- end
395
-
396
- def convert_to_term_value(value)
397
- case value
398
- when DateTime, Time
399
- value.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
400
- when Date
401
- value.to_time(:local).strftime("%Y-%m-%dT%H:%M:%SZ")
402
- else
403
- value.to_s
404
- end
405
- end
406
-
407
292
  ##
408
293
  # The key to use to retrieve the grouped field to display
409
294
  def grouped_key_for_results
data/lib/blacklight.rb CHANGED
@@ -99,7 +99,7 @@ module Blacklight
99
99
  end
100
100
 
101
101
  def self.logger
102
- @logger ||= (::Rails.logger if defined? Rails && Rails.respond_to?(:logger))
102
+ @logger ||= ::Rails.logger
103
103
  end
104
104
 
105
105
  def self.logger= logger
@@ -10,7 +10,7 @@ module Blacklight
10
10
  <<~CONTENT
11
11
  pin "@github/auto-complete-element", to: "https://cdn.skypack.dev/@github/auto-complete-element"
12
12
  pin "@popperjs/core", to: "https://ga.jspm.io/npm:@popperjs/core@2.11.6/dist/umd/popper.min.js"
13
- pin "bootstrap", to: "https://ga.jspm.io/npm:bootstrap@#{(defined?(Bootstrap) && Bootstrap::VERSION) || '5.3.3'}/dist/js/bootstrap.js"
13
+ pin "bootstrap", to: "https://ga.jspm.io/npm:bootstrap@#{(defined?(Bootstrap) && Bootstrap::VERSION) || '5.3.5'}/dist/js/bootstrap.js"
14
14
  CONTENT
15
15
  end
16
16
 
@@ -49,10 +49,8 @@ module Blacklight
49
49
  else
50
50
  append_to_file 'app/assets/stylesheets/application.css' do
51
51
  <<~CONTENT
52
- /*
53
- *= require blacklight
54
- */
55
- @import url(https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css);
52
+ @import url(https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/css/bootstrap.min.css);
53
+ @import url("blacklight.css");
56
54
  CONTENT
57
55
  end
58
56
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Blacklight
4
4
  class AssetsGenerator < Rails::Generators::Base
5
- class_option :'bootstrap-version', type: :string, default: ENV.fetch('BOOTSTRAP_VERSION', '5.3.3'), desc: "Set the generated app's bootstrap version"
5
+ class_option :'bootstrap-version', type: :string, default: ENV.fetch('BOOTSTRAP_VERSION', '5.3.5'), desc: "Set the generated app's bootstrap version"
6
6
 
7
7
  def run_asset_pipeline_specific_generator
8
8
  generated_options = "--bootstrap-version='#{options[:'bootstrap-version']}'" if options[:'bootstrap-version']
@@ -27,7 +27,7 @@ module Blacklight
27
27
  private
28
28
 
29
29
  def rspec_installed?
30
- defined?(RSpec) && defined?(RSpec::Rails)
30
+ defined?(RSpec::Rails)
31
31
  end
32
32
  end
33
33
  end
@@ -1,5 +1,7 @@
1
1
  # Place any default configuration for solr_wrapper here
2
2
  # port: 8983
3
+ env:
4
+ SOLR_MODULES: analysis-extras
3
5
  collection:
4
6
  dir: solr/conf/
5
7
  name: blacklight-core
@@ -105,9 +105,11 @@ class <%= controller_name.classify %>Controller < ApplicationController
105
105
  # :show may be set to false if you don't want the facet to be drawn in the
106
106
  # facet bar
107
107
  #
108
- # set :index_range to true if you want the facet pagination view to have facet prefix-based navigation
108
+ # Set :index_range to true if you want the facet pagination view to have facet prefix-based navigation.
109
109
  # (useful when user clicks "more" on a large facet and wants to navigate alphabetically across a large set of results)
110
110
  # :index_range can be an array or range of prefixes that will be used to create the navigation (note: It is case sensitive when searching values)
111
+ # This control only displays when the user has selected "A-Z Sort" (You make make this the default by setting "sort: 'index'"
112
+ # in the facet config)
111
113
 
112
114
  config.add_facet_field 'format', label: 'Format'
113
115
  config.add_facet_field 'pub_date_ssim', label: 'Publication Year', single: true
@@ -47,7 +47,6 @@
47
47
  full_title_tsim
48
48
  short_title_tsim
49
49
  alternative_title_tsim
50
- active_fedora_model_ssi
51
50
  title_tsim
52
51
  author_tsim
53
52
  subject_tsim
@@ -84,7 +83,6 @@
84
83
  <str name="facet">true</str>
85
84
  <str name="facet.mincount">1</str>
86
85
  <str name="facet.limit">10</str>
87
- <str name="facet.field">active_fedora_model_ssi</str>
88
86
  <str name="facet.field">subject_ssim</str>
89
87
 
90
88
  <str name="spellcheck">true</str>
@@ -116,7 +114,6 @@
116
114
  full_title_tsim
117
115
  short_title_tsim
118
116
  alternative_title_tsim
119
- active_fedora_model_ssi
120
117
  title_tsim
121
118
  author_tsim
122
119
  subject_tsim
@@ -153,7 +150,6 @@
153
150
  <str name="facet">true</str>
154
151
  <str name="facet.mincount">1</str>
155
152
  <str name="facet.limit">10</str>
156
- <str name="facet.field">active_fedora_model_ssi</str>
157
153
  <str name="facet.field">subject_ssim</str>
158
154
 
159
155
  <str name="spellcheck">true</str>
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blacklight-frontend",
3
- "version": "9.0.0-beta1",
3
+ "version": "9.0.0-beta2",
4
4
  "description": "The frontend code and styles for Blacklight",
5
5
  "exports": {
6
6
  "./blacklight.esm.js": "./app/assets/javascripts/blacklight/blacklight.esm.js",
@@ -34,13 +34,13 @@
34
34
  "rollup": "^4.24.0",
35
35
  "rollup-plugin-includepaths": "^0.2.4",
36
36
  "sass": "^1.80.3",
37
- "bootstrap": "^5.3.3"
37
+ "bootstrap": "^5.3.5"
38
38
  },
39
39
  "browserslist": [
40
40
  "defaults",
41
41
  "not IE 11"
42
42
  ],
43
43
  "dependencies": {
44
- "bootstrap": ">=4.3.1 <6.0.0"
44
+ "bootstrap": ">=5.3.5 <6.0.0"
45
45
  }
46
46
  }
@@ -3,49 +3,45 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe Blacklight::AdvancedSearchFormComponent, type: :component do
6
- subject(:render) do
7
- component.render_in(view_context)
8
- end
9
-
10
6
  let(:component) { described_class.new(url: '/whatever', response: response, params: params) }
11
- let(:response) { Blacklight::Solr::Response.new({ facet_counts: { facet_fields: { format: { 'Book' => 10, 'CD' => 5 } } } }.with_indifferent_access, {}) }
12
- let(:params) { {} }
13
-
14
- let(:rendered) do
15
- Capybara::Node::Simple.new(render)
7
+ let(:response) { Blacklight::Solr::Response.new({ facet_counts: { facet_fields: { format: { 'Book' => 10, 'CD' => 5 } } } }.with_indifferent_access, search_builder) }
8
+ let(:search_builder) do
9
+ Blacklight::SearchBuilder.new(view_context)
16
10
  end
11
+ let(:params) { {} }
17
12
 
18
- let(:view_context) { controller.view_context }
13
+ let(:view_context) { vc_test_controller.view_context }
19
14
 
20
15
  before do
21
16
  allow(view_context).to receive(:facet_limit_for).and_return(nil)
17
+ render_inline component
22
18
  end
23
19
 
24
20
  context 'with additional parameters' do
25
21
  let(:params) { { some: :parameter, an_array: [1, 2] } }
26
22
 
27
23
  it 'adds additional parameters as hidden fields' do
28
- expect(rendered).to have_field 'some', with: 'parameter', type: :hidden
29
- expect(rendered).to have_field 'an_array[]', with: '1', type: :hidden
30
- expect(rendered).to have_field 'an_array[]', with: '2', type: :hidden
24
+ expect(page).to have_field 'some', with: 'parameter', type: :hidden
25
+ expect(page).to have_field 'an_array[]', with: '1', type: :hidden
26
+ expect(page).to have_field 'an_array[]', with: '2', type: :hidden
31
27
  end
32
28
  end
33
29
 
34
30
  it 'has text fields for each search field' do
35
- expect(rendered).to have_css '.advanced-search-field', count: 4
36
- expect(rendered).to have_field 'clause_0_field', with: 'all_fields', type: :hidden
37
- expect(rendered).to have_field 'clause_1_field', with: 'title', type: :hidden
38
- expect(rendered).to have_field 'clause_2_field', with: 'author', type: :hidden
39
- expect(rendered).to have_field 'clause_3_field', with: 'subject', type: :hidden
31
+ expect(page).to have_css '.advanced-search-field', count: 4
32
+ expect(page).to have_field 'clause_0_field', with: 'all_fields', type: :hidden
33
+ expect(page).to have_field 'clause_1_field', with: 'title', type: :hidden
34
+ expect(page).to have_field 'clause_2_field', with: 'author', type: :hidden
35
+ expect(page).to have_field 'clause_3_field', with: 'subject', type: :hidden
40
36
  end
41
37
 
42
38
  it 'has filters' do
43
- expect(rendered).to have_css '.blacklight-format'
44
- expect(rendered).to have_field 'f_inclusive[format][]', with: 'Book'
45
- expect(rendered).to have_field 'f_inclusive[format][]', with: 'CD'
39
+ expect(page).to have_css '.blacklight-format'
40
+ expect(page).to have_field 'f_inclusive[format][]', with: 'Book'
41
+ expect(page).to have_field 'f_inclusive[format][]', with: 'CD'
46
42
  end
47
43
 
48
44
  it 'has a sort field' do
49
- expect(rendered).to have_select 'sort', options: %w[relevance year author title]
45
+ expect(page).to have_select 'sort', options: %w[relevance year author title]
50
46
  end
51
47
  end