blacklight 9.0.0.beta1 → 9.0.0

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 (263) hide show
  1. checksums.yaml +4 -4
  2. data/.docker/app/Dockerfile +2 -1
  3. data/.github/matrix.json +55 -0
  4. data/.github/workflows/build.yml +16 -0
  5. data/.github/workflows/lint.yml +25 -0
  6. data/.github/workflows/main.yml +22 -0
  7. data/.github/workflows/release_7_x_scheduled.yml +39 -0
  8. data/.github/workflows/release_8_x_scheduled.yml +39 -0
  9. data/.github/workflows/test.yml +53 -0
  10. data/.rubocop.yml +81 -3
  11. data/.rubocop_todo.yml +46 -71
  12. data/.solr_wrapper.yml +3 -1
  13. data/README.md +2 -2
  14. data/VERSION +1 -1
  15. data/app/assets/builds/blacklight.css +51 -38
  16. data/app/assets/javascripts/blacklight/blacklight.esm.js +62 -77
  17. data/app/assets/javascripts/blacklight/blacklight.esm.js.map +1 -1
  18. data/app/assets/javascripts/blacklight/blacklight.js +62 -77
  19. data/app/assets/javascripts/blacklight/blacklight.js.map +1 -1
  20. data/app/assets/stylesheets/blacklight/_blacklight_base.scss +0 -1
  21. data/app/assets/stylesheets/blacklight/_bootstrap_overrides.scss +4 -0
  22. data/app/assets/stylesheets/blacklight/_facets.scss +37 -29
  23. data/app/assets/stylesheets/blacklight/_header.scss +4 -0
  24. data/app/assets/stylesheets/blacklight/_modal.scss +9 -8
  25. data/app/assets/stylesheets/blacklight/_pagination.scss +1 -3
  26. data/app/assets/stylesheets/blacklight/_search_history.scss +0 -4
  27. data/app/assets/stylesheets/blacklight/blacklight_defaults.scss +3 -0
  28. data/app/components/blacklight/advanced_search_form_component.html.erb +4 -4
  29. data/app/components/blacklight/advanced_search_form_component.rb +6 -5
  30. data/app/components/blacklight/constraint_component.html.erb +1 -5
  31. data/app/components/blacklight/constraint_component.rb +11 -0
  32. data/app/components/blacklight/constraint_layout_component.html.erb +1 -6
  33. data/app/components/blacklight/constraint_layout_component.rb +9 -0
  34. data/app/components/blacklight/constraints_component.html.erb +3 -8
  35. data/app/components/blacklight/constraints_component.rb +59 -14
  36. data/app/components/blacklight/document/action_component.rb +1 -3
  37. data/app/components/blacklight/document/bookmark_component.html.erb +3 -3
  38. data/app/components/blacklight/document/bookmark_component.rb +10 -4
  39. data/app/components/blacklight/document/group_component.html.erb +1 -1
  40. data/app/components/blacklight/document/more_like_this_component.rb +2 -2
  41. data/app/components/blacklight/document/page_header_component.rb +3 -3
  42. data/app/components/blacklight/document/thumbnail_component.html.erb +3 -7
  43. data/app/components/blacklight/document/thumbnail_component.rb +7 -6
  44. data/app/components/blacklight/document_component.html.erb +3 -3
  45. data/app/components/blacklight/document_component.rb +22 -26
  46. data/app/components/blacklight/document_title_component.rb +6 -10
  47. data/app/components/blacklight/facet_field_checkboxes_component.rb +4 -18
  48. data/app/components/blacklight/facet_field_component.rb +4 -15
  49. data/app/components/blacklight/facet_field_filter_component.rb +4 -19
  50. data/app/components/blacklight/facet_field_inclusive_constraint_component.rb +4 -23
  51. data/app/components/blacklight/facet_field_list_component.rb +4 -30
  52. data/app/components/blacklight/facet_field_no_layout_component.rb +4 -8
  53. data/app/components/blacklight/facet_field_pagination_component.html.erb +2 -2
  54. data/app/components/blacklight/facet_item_component.rb +4 -72
  55. data/app/components/blacklight/facet_item_pivot_component.rb +8 -4
  56. data/app/components/blacklight/{facet_field_checkboxes_component.html.erb → facets/checkboxes_component.html.erb} +4 -4
  57. data/app/components/blacklight/facets/checkboxes_component.rb +26 -0
  58. data/app/components/blacklight/facets/count_component.rb +23 -0
  59. data/app/components/blacklight/{facet_field_component.html.erb → facets/field_component.html.erb} +1 -3
  60. data/app/components/blacklight/facets/field_component.rb +23 -0
  61. data/app/components/blacklight/facets/filters_component.html.erb +4 -0
  62. data/app/components/blacklight/facets/filters_component.rb +39 -0
  63. data/app/components/blacklight/{facet_field_inclusive_constraint_component.html.erb → facets/inclusive_constraint_component.html.erb} +1 -1
  64. data/app/components/blacklight/facets/inclusive_constraint_component.rb +31 -0
  65. data/app/components/blacklight/{facet_field_filter_component.html.erb → facets/index_navigation_component.html.erb} +1 -1
  66. data/app/components/blacklight/facets/index_navigation_component.rb +32 -0
  67. data/app/components/blacklight/facets/item_component.rb +76 -0
  68. data/app/components/blacklight/facets/list_component.html.erb +11 -0
  69. data/app/components/blacklight/facets/list_component.rb +46 -0
  70. data/app/components/blacklight/facets/no_layout_component.rb +16 -0
  71. data/app/components/blacklight/facets/pivot_list_component.rb +14 -0
  72. data/app/components/blacklight/facets/selected_value_component.rb +29 -0
  73. data/app/components/blacklight/facets/suggest_component.html.erb +17 -0
  74. data/app/components/blacklight/facets/suggest_component.rb +21 -0
  75. data/app/components/blacklight/header_component.rb +2 -2
  76. data/app/components/blacklight/icons/remove_component.rb +2 -2
  77. data/app/components/blacklight/metadata_field_component.html.erb +2 -2
  78. data/app/components/blacklight/metadata_field_component.rb +2 -1
  79. data/app/components/blacklight/metadata_field_layout_component.rb +9 -4
  80. data/app/components/blacklight/metadata_field_plain_text_layout_component.rb +2 -2
  81. data/app/components/blacklight/response/facet_group_component.html.erb +3 -3
  82. data/app/components/blacklight/response/facet_group_component.rb +9 -1
  83. data/app/components/blacklight/search_bar_component.html.erb +2 -2
  84. data/app/components/blacklight/system/dropdown_component.html.erb +1 -1
  85. data/app/components/blacklight/system/dropdown_component.rb +1 -1
  86. data/app/components/blacklight/system/flash_message_component.html.erb +1 -1
  87. data/app/components/blacklight/system/flash_message_component.rb +0 -9
  88. data/app/components/blacklight/system/modal_component.html.erb +1 -2
  89. data/app/components/blacklight/top_navbar_component.html.erb +2 -2
  90. data/app/controllers/concerns/blacklight/bookmarks.rb +13 -3
  91. data/app/controllers/concerns/blacklight/catalog.rb +27 -30
  92. data/app/controllers/concerns/blacklight/controller.rb +1 -1
  93. data/app/controllers/concerns/blacklight/search_context.rb +1 -1
  94. data/app/controllers/concerns/blacklight/searchable.rb +1 -1
  95. data/app/helpers/blacklight/catalog_helper_behavior.rb +5 -3
  96. data/app/helpers/blacklight/configuration_helper_behavior.rb +2 -2
  97. data/app/helpers/blacklight/document_helper_behavior.rb +3 -1
  98. data/app/helpers/blacklight/facets_helper_behavior.rb +7 -12
  99. data/app/helpers/blacklight/icon_helper_behavior.rb +2 -2
  100. data/app/javascript/blacklight-frontend/bookmark_toggle.js +7 -2
  101. data/app/javascript/blacklight-frontend/button_focus.js +1 -1
  102. data/app/javascript/blacklight-frontend/checkbox_submit.js +9 -2
  103. data/app/javascript/blacklight-frontend/debounce.js +1 -1
  104. data/app/javascript/blacklight-frontend/facet_suggest.js +27 -3
  105. data/app/javascript/blacklight-frontend/index.js +0 -2
  106. data/app/javascript/blacklight-frontend/modal.js +15 -8
  107. data/app/javascript/blacklight-frontend/search_context.js +3 -2
  108. data/app/presenters/blacklight/constraint_presenter.rb +22 -0
  109. data/app/presenters/blacklight/document_presenter.rb +6 -5
  110. data/app/presenters/blacklight/facet_field_presenter.rb +18 -2
  111. data/app/presenters/blacklight/facet_grouped_item_presenter.rb +6 -0
  112. data/app/presenters/blacklight/facet_item_pivot_presenter.rb +1 -5
  113. data/app/presenters/blacklight/facet_item_presenter.rb +5 -18
  114. data/app/presenters/blacklight/field_presenter.rb +4 -2
  115. data/app/presenters/blacklight/json_presenter.rb +8 -4
  116. data/app/presenters/blacklight/rendering/abstract_step.rb +7 -1
  117. data/app/presenters/blacklight/rendering/helper_method.rb +4 -4
  118. data/app/presenters/blacklight/rendering/join.rb +11 -7
  119. data/app/presenters/blacklight/rendering/terminator.rb +1 -1
  120. data/app/services/blacklight/field_retriever.rb +1 -1
  121. data/app/services/blacklight/search_service.rb +10 -8
  122. data/app/values/blacklight/types.rb +2 -2
  123. data/app/views/blacklight/nav/_bookmark.html.erb +1 -1
  124. data/app/views/catalog/_document.atom.builder +1 -1
  125. data/app/views/catalog/_document.html.erb +1 -1
  126. data/app/views/catalog/_email_form.html.erb +4 -4
  127. data/app/views/catalog/_home_text.html.erb +2 -2
  128. data/app/views/catalog/_show_main_content.html.erb +9 -5
  129. data/app/views/catalog/_sms_form.html.erb +4 -4
  130. data/app/views/catalog/_sort_and_per_page.html.erb +1 -1
  131. data/app/views/catalog/advanced_search.html.erb +1 -1
  132. data/app/views/catalog/facet.html.erb +8 -10
  133. data/app/views/catalog/index.html.erb +0 -1
  134. data/app/views/catalog/index.json.jbuilder +5 -3
  135. data/app/views/catalog/show.html.erb +2 -2
  136. data/app/views/layouts/blacklight/base.html.erb +1 -1
  137. data/blacklight.gemspec +1 -1
  138. data/config/locales/blacklight.ar.yml +14 -14
  139. data/config/locales/blacklight.ca.yml +2 -2
  140. data/config/locales/blacklight.de.yml +13 -13
  141. data/config/locales/blacklight.en.yml +3 -3
  142. data/config/locales/blacklight.es.yml +13 -13
  143. data/config/locales/blacklight.fr.yml +14 -14
  144. data/config/locales/blacklight.hu.yml +15 -15
  145. data/config/locales/blacklight.it.yml +16 -16
  146. data/config/locales/blacklight.nl.yml +13 -13
  147. data/config/locales/blacklight.pt-BR.yml +15 -15
  148. data/config/locales/blacklight.sq.yml +14 -14
  149. data/config/locales/blacklight.zh.yml +12 -12
  150. data/lib/blacklight/abstract_repository.rb +2 -2
  151. data/lib/blacklight/component.rb +7 -1
  152. data/lib/blacklight/configuration/context.rb +3 -3
  153. data/lib/blacklight/configuration/facet_field.rb +11 -6
  154. data/lib/blacklight/configuration/field.rb +4 -4
  155. data/lib/blacklight/configuration/fields.rb +0 -1
  156. data/lib/blacklight/configuration/search_field.rb +1 -1
  157. data/lib/blacklight/configuration/view_config.rb +32 -18
  158. data/lib/blacklight/configuration.rb +64 -10
  159. data/lib/blacklight/nested_open_struct_with_hash_access.rb +1 -1
  160. data/lib/blacklight/open_struct_with_hash_access.rb +2 -2
  161. data/lib/blacklight/routes/searchable.rb +1 -1
  162. data/lib/blacklight/search_builder.rb +2 -1
  163. data/lib/blacklight/search_state/filter_field.rb +4 -4
  164. data/lib/blacklight/search_state/pivot_filter_field.rb +5 -5
  165. data/lib/blacklight/search_state.rb +2 -0
  166. data/lib/blacklight/solr/abstract_filter_query_builder.rb +77 -0
  167. data/lib/blacklight/solr/default_filter_query_builder.rb +20 -0
  168. data/lib/blacklight/solr/field_reflection_search_builder.rb +11 -0
  169. data/lib/blacklight/solr/repository.rb +17 -15
  170. data/lib/blacklight/solr/response/facets.rb +2 -2
  171. data/lib/blacklight/solr/response/params.rb +0 -4
  172. data/lib/blacklight/solr/response.rb +5 -1
  173. data/lib/blacklight/solr/search_builder_behavior.rb +48 -97
  174. data/lib/blacklight/solr/single_doc_search_builder.rb +25 -0
  175. data/lib/blacklight.rb +6 -4
  176. data/lib/generators/blacklight/assets/importmap_generator.rb +3 -5
  177. data/lib/generators/blacklight/assets_generator.rb +1 -1
  178. data/lib/generators/blacklight/search_builder_generator.rb +1 -1
  179. data/lib/generators/blacklight/templates/.solr_wrapper.yml +3 -1
  180. data/lib/generators/blacklight/templates/catalog_controller.rb +34 -8
  181. data/lib/generators/blacklight/templates/solr/conf/solrconfig.xml +0 -71
  182. data/package.json +3 -3
  183. data/spec/components/blacklight/advanced_search_form_component_spec.rb +18 -22
  184. data/spec/components/blacklight/constraint_layout_component_spec.rb +8 -8
  185. data/spec/components/blacklight/constraints_component_spec.rb +11 -11
  186. data/spec/components/blacklight/document/action_component_spec.rb +23 -15
  187. data/spec/components/blacklight/document/group_component_spec.rb +10 -15
  188. data/spec/components/blacklight/document/page_header_component_spec.rb +35 -28
  189. data/spec/components/blacklight/document/sidebar_component_spec.rb +5 -11
  190. data/spec/components/blacklight/document_component_spec.rb +105 -79
  191. data/spec/components/blacklight/facet_component_spec.rb +12 -8
  192. data/spec/components/blacklight/facet_item_pivot_component_spec.rb +12 -12
  193. data/spec/components/blacklight/{facet_field_checkboxes_component_spec.rb → facets/checkboxes_component_spec.rb} +13 -13
  194. data/spec/components/blacklight/facets/filters_component_spec.rb +36 -0
  195. data/spec/components/blacklight/facets/index_navigation_component_spec.rb +41 -0
  196. data/spec/components/blacklight/{facet_item_component_spec.rb → facets/item_component_spec.rb} +10 -10
  197. data/spec/components/blacklight/{facet_field_list_component_spec.rb → facets/list_component_spec.rb} +34 -23
  198. data/spec/components/blacklight/facets/pivot_list_component_spec.rb +53 -0
  199. data/spec/components/blacklight/facets/suggest_component_spec.rb +82 -0
  200. data/spec/components/blacklight/header_component_spec.rb +2 -4
  201. data/spec/components/blacklight/hidden_search_state_component_spec.rb +7 -7
  202. data/spec/components/blacklight/metadata_field_component_spec.rb +17 -15
  203. data/spec/components/blacklight/response/facet_group_component_spec.rb +37 -0
  204. data/spec/components/blacklight/response/pagination_component_spec.rb +1 -1
  205. data/spec/components/blacklight/response/spellcheck_component_spec.rb +1 -1
  206. data/spec/components/blacklight/search_bar_component_spec.rb +28 -5
  207. data/spec/components/blacklight/search_context/server_applied_params_component_spec.rb +2 -2
  208. data/spec/components/blacklight/search_context/server_item_pagination_component_spec.rb +3 -5
  209. data/spec/components/blacklight/skip_link_component_spec.rb +8 -11
  210. data/spec/components/blacklight/start_over_button_component_spec.rb +4 -4
  211. data/spec/components/blacklight/system/dropdown_component_spec.rb +26 -0
  212. data/spec/components/blacklight/system/flash_message_component_spec.rb +7 -11
  213. data/spec/controllers/blacklight/catalog_spec.rb +1 -1
  214. data/spec/controllers/catalog_controller_spec.rb +12 -20
  215. data/spec/features/advanced_search_spec.rb +42 -21
  216. data/spec/features/facets_spec.rb +84 -12
  217. data/spec/features/modal_spec.rb +1 -1
  218. data/spec/features/search_filters_spec.rb +6 -4
  219. data/spec/features/search_spec.rb +3 -3
  220. data/spec/helpers/blacklight/facets_helper_behavior_spec.rb +10 -0
  221. data/spec/lib/blacklight/configuration/facet_field_spec.rb +2 -2
  222. data/spec/lib/blacklight/parameters_spec.rb +12 -1
  223. data/spec/lib/blacklight/search_state/filter_field_spec.rb +18 -0
  224. data/spec/models/blacklight/configuration_spec.rb +178 -28
  225. data/spec/models/blacklight/solr/default_filter_query_builder_spec.rb +72 -0
  226. data/spec/models/blacklight/solr/document_spec.rb +0 -4
  227. data/spec/models/blacklight/solr/repository_spec.rb +37 -29
  228. data/spec/models/blacklight/solr/response/facets_spec.rb +86 -40
  229. data/spec/models/blacklight/solr/response/group_response_spec.rb +8 -5
  230. data/spec/models/blacklight/solr/response/group_spec.rb +9 -5
  231. data/spec/models/blacklight/solr/response_spec.rb +96 -64
  232. data/spec/models/blacklight/solr/search_builder_behavior_spec.rb +38 -57
  233. data/spec/models/solr_document_spec.rb +5 -1
  234. data/spec/presenters/blacklight/constraint_presenter_spec.rb +32 -0
  235. data/spec/presenters/blacklight/document_presenter_spec.rb +3 -3
  236. data/spec/presenters/blacklight/facet_item_presenter_spec.rb +0 -7
  237. data/spec/presenters/blacklight/field_presenter_spec.rb +103 -22
  238. data/spec/presenters/blacklight/json_presenter_spec.rb +17 -0
  239. data/spec/presenters/blacklight/rendering/pipeline_spec.rb +130 -14
  240. data/spec/services/blacklight/search_service_spec.rb +6 -27
  241. data/spec/spec_helper.rb +0 -1
  242. data/spec/support/presenter_test_helpers.rb +1 -1
  243. data/spec/support/view_component_test_helpers.rb +0 -18
  244. data/spec/views/catalog/facet.html.erb_spec.rb +10 -3
  245. data/spec/views/catalog/index.atom.builder_spec.rb +8 -3
  246. data/spec/views/catalog/index.html.erb_spec.rb +3 -1
  247. metadata +69 -38
  248. data/.github/workflows/ruby.yml +0 -98
  249. data/app/assets/stylesheets/blacklight/_icons.scss +0 -4
  250. data/app/components/blacklight/facet_field_list_component.html.erb +0 -19
  251. data/app/components/blacklight/search/facet_suggest_input.html.erb +0 -9
  252. data/app/components/blacklight/search/facet_suggest_input.rb +0 -16
  253. data/app/javascript/blacklight-frontend/modalForm.js +0 -60
  254. data/app/views/catalog/_facet_index_navigation.html.erb +0 -1
  255. data/app/views/catalog/_facet_layout.html.erb +0 -8
  256. data/app/views/catalog/_facet_pagination.html.erb +0 -1
  257. data/app/views/catalog/_facet_pivot.html.erb +0 -3
  258. data/app/views/shared/_sitelinks_search_box.html.erb +0 -12
  259. data/spec/components/blacklight/document_metadata_component_spec.rb +0 -0
  260. data/spec/components/blacklight/search/facet_suggest_input_spec.rb +0 -33
  261. data/spec/features/sitelinks_search_box_spec.rb +0 -13
  262. data/spec/views/catalog/_facet_index_navigation.html.erb_spec.rb +0 -43
  263. data/spec/views/catalog/_facet_layout.html.erb_spec.rb +0 -41
@@ -1,17 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Blacklight::Solr
4
+ # This depends on being imported into a class that extends AbstractSearchBuilder
4
5
  module SearchBuilderBehavior
5
6
  extend ActiveSupport::Concern
6
7
 
7
8
  included do
8
9
  self.default_processor_chain = [
9
- :default_solr_parameters, :add_search_field_default_parameters,
10
- :add_query_to_solr, :add_facet_fq_to_solr,
11
- :add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr,
12
- :add_sorting_to_solr, :add_group_config_to_solr,
13
- :add_facet_paging_to_solr, :add_facet_suggestion_parameters,
10
+ :default_solr_parameters,
11
+ :add_search_field_default_parameters,
12
+ :add_query_to_solr,
13
+ :add_facet_fq_to_solr,
14
+ :add_facetting_to_solr,
15
+ :add_solr_fields_to_query,
16
+ :add_paging_to_solr,
17
+ :add_sorting_to_solr,
18
+ :add_group_config_to_solr,
14
19
  :add_adv_search_clauses,
20
+ :add_facets_for_advanced_search_form,
21
+ :add_facet_paging_to_solr,
22
+ :add_facet_suggestion_parameters,
15
23
  :add_additional_filters
16
24
  ]
17
25
  end
@@ -96,6 +104,13 @@ module Blacklight::Solr
96
104
  def add_adv_search_clauses(solr_parameters)
97
105
  return if search_state.clause_params.blank?
98
106
 
107
+ # We need to specify lucene as the top-level defType when using JSON Query DSL in Solr versions
108
+ # between 7.2.0 & 9.4.0. After 9.4.0 this is no longer necessary, but also not harmful to include.
109
+ solr_parameters[:defType] = 'lucene'
110
+
111
+ # Disable spellcheck, which doesn't work when using JSON Query DSL
112
+ solr_parameters[:spellcheck] = 'false'
113
+
99
114
  defaults = { must: [], must_not: [], should: [] }
100
115
  default_op = blacklight_params[:op]&.to_sym || :must
101
116
  solr_parameters[:mm] = 1 if default_op == :should && search_state.clause_params.values.any? { |clause| }
@@ -118,6 +133,16 @@ module Blacklight::Solr
118
133
  [op, field.clause_params.transform_values { |v| v.merge(query: clause[:query]) }]
119
134
  end
120
135
 
136
+ # Merge the advanced search form parameters into the solr parameters
137
+ # @param [Hash] solr_parameters the current solr parameters
138
+ # @return [Hash] the solr parameters with the additional advanced search form parameters
139
+ def add_facets_for_advanced_search_form(solr_parameters)
140
+ return unless search_state.controller&.action_name == 'advanced_search' &&
141
+ blacklight_config.advanced_search[:form_solr_parameters]
142
+
143
+ solr_parameters.merge!(blacklight_config.advanced_search[:form_solr_parameters])
144
+ end
145
+
121
146
  ##
122
147
  # Add any existing facet limits, stored in app-level HTTP query
123
148
  # as :f, to solr as appropriate :fq query.
@@ -128,25 +153,19 @@ module Blacklight::Solr
128
153
  end
129
154
 
130
155
  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
156
+ filter_query_builder_class_or_proc = filter.config.filter_query_builder || DefaultFilterQueryBuilder
157
+ if filter_query_builder_class_or_proc.is_a?(Class)
158
+ filter_query_builder = filter_query_builder_class_or_proc.new(blacklight_config: blacklight_config)
159
+ filter_query, subqueries = filter_query_builder.call(filter, solr_parameters)
138
160
  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
161
+ # TODO: Maybe deprecate proc?
162
+ filter_query, subqueries = filter_query_builder_class_or_proc.call(self, filter, solr_parameters)
163
+ end
164
+
165
+ Array(filter_query).each do |fq|
166
+ solr_parameters.append_filter_query(fq)
149
167
  end
168
+ solr_parameters.merge!(subqueries) if subqueries
150
169
  end
151
170
  end
152
171
 
@@ -190,10 +209,8 @@ module Blacklight::Solr
190
209
  solr_parameters[:"f.#{facet.field}.facet.sort"] = facet.sort
191
210
  end
192
211
 
193
- if facet.solr_params
194
- facet.solr_params.each do |k, v|
195
- solr_parameters[:"f.#{facet.field}.#{k}"] = v
196
- end
212
+ facet.solr_params&.each do |k, v|
213
+ solr_parameters[:"f.#{facet.field}.#{k}"] = v
197
214
  end
198
215
 
199
216
  limit = facet_limit_with_pagination(field_name)
@@ -203,9 +220,9 @@ module Blacklight::Solr
203
220
 
204
221
  def add_solr_fields_to_query solr_parameters
205
222
  blacklight_config.show_fields.select(&method(:should_add_field_to_request?)).each_value do |field|
206
- field.solr_params.each do |k, v|
223
+ field.solr_params&.each do |k, v|
207
224
  solr_parameters[:"f.#{field.field}.#{k}"] = v
208
- end if field.solr_params
225
+ end
209
226
  end
210
227
 
211
228
  blacklight_config.index_fields.select(&method(:should_add_field_to_request?)).each_value do |field|
@@ -214,9 +231,9 @@ module Blacklight::Solr
214
231
  solr_parameters.append_highlight_field field.field
215
232
  end
216
233
 
217
- field.solr_params.each do |k, v|
234
+ field.solr_params&.each do |k, v|
218
235
  solr_parameters[:"f.#{field.field}.#{k}"] = v
219
- end if field.solr_params
236
+ end
220
237
  end
221
238
  end
222
239
 
@@ -224,8 +241,6 @@ module Blacklight::Solr
224
241
  # copy paging params from BL app over to solr, changing
225
242
  # app level per_page and page to Solr rows and start.
226
243
  def add_paging_to_solr(solr_params)
227
- rows(solr_params[:rows] || 10) if rows.nil?
228
-
229
244
  solr_params[:rows] = rows
230
245
 
231
246
  solr_params[:start] = start if start.nonzero?
@@ -294,7 +309,7 @@ module Blacklight::Solr
294
309
 
295
310
  # Look up facet limit for given facet_field. Will look at config, and
296
311
  # if config is 'true' will look up from Solr @response if available. If
297
- # no limit is avaialble, returns nil. Used from #add_facetting_to_solr
312
+ # no limit is available, returns nil. Used from #add_facetting_to_solr
298
313
  # to supply f.fieldname.facet.limit values in solr request (no @response
299
314
  # available), and used in display (with @response available) to create
300
315
  # a facet paginator with the right limit.
@@ -340,70 +355,6 @@ module Blacklight::Solr
340
355
 
341
356
  private
342
357
 
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
358
  ##
408
359
  # The key to use to retrieve the grouped field to display
409
360
  def grouped_key_for_results
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight::Solr
4
+ class SingleDocSearchBuilder < SearchBuilder
5
+ self.default_processor_chain = [:add_defaults, :add_qt, :add_unique_id]
6
+
7
+ def initialize(scope, id, other_params)
8
+ @other_params = other_params
9
+ @id = id
10
+ super(scope)
11
+ end
12
+
13
+ def add_defaults(request)
14
+ request.reverse_merge!(blacklight_config.default_document_solr_params).reverse_merge!(@other_params)
15
+ end
16
+
17
+ def add_qt(request)
18
+ request[:qt] ||= blacklight_config.document_solr_request_handler if blacklight_config.document_solr_request_handler
19
+ end
20
+
21
+ def add_unique_id(request)
22
+ request[blacklight_config.document_unique_id_param] = @id
23
+ end
24
+ end
25
+ end
data/lib/blacklight.rb CHANGED
@@ -29,14 +29,16 @@ module Blacklight
29
29
  # the class Blacklight::(name of the adapter)::Repository, e.g.
30
30
  # elastic_search => Blacklight::ElasticSearch::Repository
31
31
  def self.repository_class
32
- case connection_config[:adapter]
32
+ if connection_config && !connection_config.key?(:adapter)
33
+ raise "The value for :adapter was not found in the blacklight.yml config"
34
+ end
35
+
36
+ case connection_config&.fetch(:adapter) || 'solr'
33
37
  when 'solr'
34
38
  Blacklight::Solr::Repository
35
39
  when /::/
36
40
  connection_config[:adapter].constantize
37
41
  else
38
- raise "The value for :adapter was not found in the blacklight.yml config" unless connection_config.key? :adapter
39
-
40
42
  Blacklight.const_get("#{connection_config.fetch(:adapter)}/Repository".classify)
41
43
  end
42
44
  end
@@ -99,7 +101,7 @@ module Blacklight
99
101
  end
100
102
 
101
103
  def self.logger
102
- @logger ||= (::Rails.logger if defined? Rails && Rails.respond_to?(:logger))
104
+ @logger ||= ::Rails.logger
103
105
  end
104
106
 
105
107
  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
- dir: solr/conf/
6
+ dir: solr/
5
7
  name: blacklight-core
@@ -12,7 +12,7 @@ class <%= controller_name.classify %>Controller < ApplicationController
12
12
  # rescue_from Blacklight::Exceptions::InvalidRequest, with: :my_handling_method
13
13
 
14
14
  configure_blacklight do |config|
15
- ## Specify the style of markup to be generated (may be 4 or 5)
15
+ ## Specify the style of markup to be generated
16
16
  # config.bootstrap_version = 5
17
17
  #
18
18
  ## Class for sending and receiving requests from a search index
@@ -29,6 +29,13 @@ class <%= controller_name.classify %>Controller < ApplicationController
29
29
  #
30
30
  ## Should the raw solr document endpoint (e.g. /catalog/:id/raw) be enabled
31
31
  # config.raw_endpoint.enabled = false
32
+ #
33
+ ## Should advanced search be enabled
34
+ # config.advanced_search.enabled = true
35
+ #
36
+ ## Optional fine-tuning for advanced search, e.g., set different limits for
37
+ ## different facets.
38
+ # config.advanced_search.form_solr_parameters = {}
32
39
 
33
40
  ## Default parameters to send to solr for all search-like requests. See also SearchBuilder#processed_parameters
34
41
  config.default_solr_params = {
@@ -38,7 +45,7 @@ class <%= controller_name.classify %>Controller < ApplicationController
38
45
  # solr path which will be added to solr base url before the other solr params.
39
46
  #config.solr_path = 'select'
40
47
  #config.document_solr_path = 'get'
41
- #config.json_solr_path = 'advanced'
48
+ #config.json_solr_path = 'select'
42
49
 
43
50
  # items to show per page, each number in the array represent another option to choose from.
44
51
  #config.per_page = [10,20,50,100]
@@ -65,8 +72,8 @@ class <%= controller_name.classify %>Controller < ApplicationController
65
72
  config.add_results_collection_tool(:view_type_group)
66
73
 
67
74
  config.add_show_tools_partial(:bookmark, component: Blacklight::Document::BookmarkComponent, if: :render_bookmarks_control?)
68
- config.add_show_tools_partial(:email, callback: :email_action, validator: :validate_email_params)
69
- config.add_show_tools_partial(:sms, if: :render_sms_action?, callback: :sms_action, validator: :validate_sms_params)
75
+ config.add_show_tools_partial(:email, callback: :email_action, validator: :email_params_valid?)
76
+ config.add_show_tools_partial(:sms, if: :render_sms_action?, callback: :sms_action, validator: :sms_params_valid?)
70
77
  config.add_show_tools_partial(:citation)
71
78
 
72
79
  config.add_nav_action(:bookmark, partial: 'blacklight/nav/bookmark', if: :render_bookmarks_control?)
@@ -105,9 +112,17 @@ class <%= controller_name.classify %>Controller < ApplicationController
105
112
  # :show may be set to false if you don't want the facet to be drawn in the
106
113
  # facet bar
107
114
  #
108
- # set :index_range to true if you want the facet pagination view to have facet prefix-based navigation
115
+ # Set :include_in_advanced_search to false for any search field or facet field
116
+ # that you want to exclude from appearing in the advanced search page.
117
+ #
118
+ # Set :include_in_simple_select to false for any search field you want to render
119
+ # in the Advanced Search page but exclude from the main search box scope selector.
120
+ #
121
+ # Set :index_range to true if you want the facet pagination view to have facet prefix-based navigation.
109
122
  # (useful when user clicks "more" on a large facet and wants to navigate alphabetically across a large set of results)
110
123
  # :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)
124
+ # This control only displays when the user has selected "A-Z Sort" (You make make this the default by setting "sort: 'index'"
125
+ # in the facet config)
111
126
 
112
127
  config.add_facet_field 'format', label: 'Format'
113
128
  config.add_facet_field 'pub_date_ssim', label: 'Publication Year', single: true
@@ -117,7 +132,11 @@ class <%= controller_name.classify %>Controller < ApplicationController
117
132
  config.add_facet_field 'subject_geo_ssim', label: 'Region'
118
133
  config.add_facet_field 'subject_era_ssim', label: 'Era'
119
134
 
120
- config.add_facet_field 'example_pivot_field', label: 'Pivot Field', pivot: ['format', 'language_ssim'], collapsing: true
135
+ config.add_facet_field 'example_pivot_field',
136
+ label: 'Pivot Field',
137
+ pivot: ['language_ssim', 'subject_geo_ssim', 'subject_ssim'],
138
+ collapsing: true,
139
+ include_in_advanced_search: false
121
140
 
122
141
  config.add_facet_field 'example_query_facet_field', label: 'Publish Date', :query => {
123
142
  :years_5 => { label: 'within 5 Years', fq: "pub_date_ssim:[#{Time.zone.now.year - 5 } TO *]" },
@@ -161,7 +180,7 @@ class <%= controller_name.classify %>Controller < ApplicationController
161
180
  config.add_show_field 'isbn_ssim', label: 'ISBN'
162
181
 
163
182
  # "fielded" search configuration. Used by pulldown among other places.
164
- # For supported keys in hash, see rdoc for Blacklight::SearchFields
183
+ # For supported keys in hash, see rdoc for Blacklight::Configuration::SearchField
165
184
  #
166
185
  # Search fields will inherit the :qt solr request handler from
167
186
  # config[:default_solr_parameters], OR can specify a different one
@@ -204,7 +223,7 @@ class <%= controller_name.classify %>Controller < ApplicationController
204
223
 
205
224
  # Specifying a :qt only to show it's possible, and so our internal automated
206
225
  # tests can test it. In this case it's the same as
207
- # config[:default_solr_parameters][:qt], so isn't actually neccesary.
226
+ # config[:default_solr_parameters][:qt], so isn't actually necessary.
208
227
  config.add_search_field('subject') do |field|
209
228
  field.qt = 'search'
210
229
  field.solr_parameters = {
@@ -214,6 +233,13 @@ class <%= controller_name.classify %>Controller < ApplicationController
214
233
  }
215
234
  end
216
235
 
236
+ # Set up a default advanced search configuration by using the current
237
+ # search_fields and facet_fields configs.
238
+ if config.advanced_search.enabled
239
+ config.copy_search_field_config_to_advanced!
240
+ config.copy_facet_field_config_to_advanced!
241
+ end
242
+
217
243
  # "sort results by" select (pulldown)
218
244
  # label in pulldown is followed by the name of the Solr field to sort by and
219
245
  # whether the sort is ascending or descending (it must be asc or desc
@@ -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,76 +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
- <str name="facet.field">subject_ssim</str>
89
-
90
- <str name="spellcheck">true</str>
91
- <str name="spellcheck.dictionary">default</str>
92
- <str name="spellcheck.onlyMorePopular">true</str>
93
- <str name="spellcheck.extendedResults">true</str>
94
- <str name="spellcheck.collate">false</str>
95
- <str name="spellcheck.count">5</str>
96
-
97
- </lst>
98
- <arr name="last-components">
99
- <str>spellcheck</str>
100
- </arr>
101
- </requestHandler>
102
-
103
- <requestHandler name="/advanced" class="solr.SearchHandler">
104
- <!-- a lucene request handler for using the JSON Query DSL,
105
- specifically for advanced search.
106
- Using a separate requestHandler is a workaround to
107
- https://issues.apache.org/jira/browse/SOLR-16916, although
108
- it could be desirable for other reasons as well.
109
- -->
110
- <lst name="defaults">
111
- <str name="defType">lucene</str>
112
- <str name="echoParams">explicit</str>
113
- <str name="df">title_tsim</str>
114
- <str name="qf">
115
- id
116
- full_title_tsim
117
- short_title_tsim
118
- alternative_title_tsim
119
- active_fedora_model_ssi
120
- title_tsim
121
- author_tsim
122
- subject_tsim
123
- all_text_timv
124
- </str>
125
- <str name="pf">
126
- all_text_timv^10
127
- </str>
128
-
129
- <str name="author_qf">
130
- author_tsim
131
- </str>
132
- <str name="author_pf">
133
- </str>
134
- <str name="title_qf">
135
- title_tsim
136
- full_title_tsim
137
- short_title_tsim
138
- alternative_title_tsim
139
- </str>
140
- <str name="title_pf">
141
- </str>
142
- <str name="subject_qf">
143
- subject_tsim
144
- </str>
145
- <str name="subject_pf">
146
- </str>
147
-
148
- <str name="fl">
149
- *,
150
- score
151
- </str>
152
-
153
- <str name="facet">true</str>
154
- <str name="facet.mincount">1</str>
155
- <str name="facet.limit">10</str>
156
- <str name="facet.field">active_fedora_model_ssi</str>
157
86
  <str name="facet.field">subject_ssim</str>
158
87
 
159
88
  <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",
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