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
@@ -27,8 +27,8 @@
27
27
  <div class="limit-criteria mb-4">
28
28
  <h2 class="limit-criteria-heading h3"><%= t('blacklight.advanced_search.form.limit_criteria_heading_html')%></h2>
29
29
 
30
- <div id="advanced_search_facets" class="limit_input row">
31
- <div class="advanced-facet-limits panel-group col-md-9 offset-md-3">
30
+ <div id="advanced_search_facets" class="facets limit_input row">
31
+ <div class="advanced-facet-limits accordion col-md-9 offset-md-3">
32
32
  <% search_filter_controls.each do |control| %>
33
33
  <%= control %>
34
34
  <% end %>
@@ -39,7 +39,7 @@
39
39
  </div>
40
40
 
41
41
  <% if sort_fields_select %>
42
- <div class="form-group row mb-4">
42
+ <div class="row mb-4">
43
43
  <%= content_tag :h2, t('blacklight.advanced_search.form.sort_label'), id: 'advanced-search-sort-label', class: 'col-md-3 text-md-right' %>
44
44
  <div class="col-md-9">
45
45
  <%= sort_fields_select %>
@@ -47,7 +47,7 @@
47
47
  </div>
48
48
  <% end %>
49
49
 
50
- <div class="form-group row">
50
+ <div class="row">
51
51
  <div class="submit-buttons col-md-9 offset-md-3">
52
52
  <%= submit_tag t('blacklight.advanced_search.form.search_btn_html'), class: 'btn btn-primary advanced-search-submit', id: "advanced-search-submit" %>
53
53
  <%= link_to t('blacklight.advanced_search.form.start_over_html'), request.path, :class =>"btn btn-link advanced-search-start-over" %>
@@ -11,8 +11,8 @@ module Blacklight
11
11
  component.new(facet_field: presenter, **kwargs)
12
12
  end)
13
13
 
14
- def initialize(response:, **options)
15
- super(**options)
14
+ def initialize(response:, **)
15
+ super(**)
16
16
  @response = response
17
17
  end
18
18
 
@@ -31,7 +31,7 @@ module Blacklight
31
31
  options = sort_fields.values.map { |field_config| [helpers.sort_field_label(field_config.key), field_config.key] }
32
32
  return unless options.any?
33
33
 
34
- select_tag(:sort, options_for_select(options, params[:sort]), class: "form-select custom-select sort-select w-auto", aria: { labelledby: 'advanced-search-sort-label' })
34
+ select_tag(:sort, options_for_select(options, params[:sort]), class: "form-select sort-select w-auto", aria: { labelledby: 'advanced-search-sort-label' })
35
35
  end
36
36
 
37
37
  # Filtered params to pass to hidden search fields
@@ -46,7 +46,7 @@ module Blacklight
46
46
  search_fields.values.each.with_index do |field, i|
47
47
  with_search_field_control do
48
48
  fields_for('clause[]', i, include_id: false) do |f|
49
- content_tag(:div, class: 'form-group advanced-search-field row mb-3') do
49
+ content_tag(:div, class: 'advanced-search-field row mb-3') do
50
50
  f.label(:query, field.display_label('search'), class: "col-sm-3 col-form-label text-md-right") +
51
51
  content_tag(:div, class: 'col-sm-9') do
52
52
  f.hidden_field(:field, value: field.key) +
@@ -68,7 +68,8 @@ module Blacklight
68
68
  end
69
69
 
70
70
  def initialize_constraints
71
- params = helpers.search_state.params_for_search.except :page, :f_inclusive, :q, :search_field, :op, :index, :sort
71
+ params = helpers.search_state.params_for_search.except :clause, :page, :f_inclusive, :q, :search_field, :op,
72
+ :index, :sort
72
73
 
73
74
  adv_search_context = helpers.search_state.reset(params)
74
75
 
@@ -1,5 +1 @@
1
- <%= render(@layout.new(
2
- classes: (Array(@classes) + ["filter-#{@facet_item_presenter.key.parameterize}"]).join(' '),
3
- label: @facet_item_presenter.field_label,
4
- value: @facet_item_presenter.constraint_label,
5
- remove_path: @facet_item_presenter.remove_href)) %>
1
+ <%= render @layout.new(classes: classes, label: field_label, value: constraint_label, remove_path: remove_href) %>
@@ -4,10 +4,21 @@ module Blacklight
4
4
  class ConstraintComponent < Blacklight::Component
5
5
  with_collection_parameter :facet_item_presenter
6
6
 
7
+ # @param [Blacklight::FacetItemPresenter] facet_item_presenter
8
+ # @param [Array<String>] classes
9
+ # @param [Blacklight::ConstraintLayoutComponent] layout
7
10
  def initialize(facet_item_presenter:, classes: %w[filter mx-1], layout: Blacklight::ConstraintLayoutComponent)
8
11
  @facet_item_presenter = facet_item_presenter
9
12
  @classes = classes
10
13
  @layout = layout
11
14
  end
15
+
16
+ attr_accessor :facet_item_presenter
17
+
18
+ delegate :field_label, :constraint_label, :remove_href, to: :facet_item_presenter
19
+
20
+ def classes
21
+ @classes + ["filter-#{facet_item_presenter.key.parameterize}"]
22
+ end
12
23
  end
13
24
  end
@@ -7,10 +7,5 @@
7
7
  <%= content_tag :span, @value, class: 'filter-value', title: strip_tags(@value) %>
8
8
  <% end %>
9
9
  </span>
10
- <% if @remove_path.present? %>
11
- <%= link_to(@remove_path, class: 'btn btn-outline-secondary remove') do %>
12
- <%= render Blacklight::Icons::RemoveComponent.new(aria_hidden: true) %>
13
- <span class="visually-hidden"><%= remove_aria_label %></span>
14
- <% end %>
15
- <% end %>
10
+ <%= remove_button %>
16
11
  </span>
@@ -21,5 +21,14 @@ module Blacklight
21
21
  def render?
22
22
  @value.present?
23
23
  end
24
+
25
+ def remove_button
26
+ return unless @remove_path
27
+
28
+ link_to(@remove_path, class: 'btn btn-outline-secondary remove') do
29
+ render(Blacklight::Icons::RemoveComponent.new(aria_hidden: true)) +
30
+ tag.span(remove_aria_label, class: "visually-hidden")
31
+ end
32
+ end
24
33
  end
25
34
  end
@@ -1,13 +1,6 @@
1
1
  <%= content_tag @tag || :div, id: @id, class: @classes do %>
2
- <% if @render_headers %>
3
- <h2 class="visually-hidden"><%= t('blacklight.search.search_constraints_header') %></h2>
4
- <% end %>
5
-
6
- <%= render @start_over_component.new if @start_over_component %>
2
+ <%= constraints_heading %>
7
3
 
8
- <% if @render_headers %>
9
- <span class="constraints-label visually-hidden"><%= t('blacklight.search.filters.title') %></span>
10
- <% end %>
11
4
  <% if query_constraints_area.present? %>
12
5
  <% query_constraints_area.each do |constraint| %>
13
6
  <%= constraint %>
@@ -27,4 +20,6 @@
27
20
  <% additional_constraints.each do |constraints| %>
28
21
  <%= constraints %>
29
22
  <% end %>
23
+
24
+ <%= render @start_over_component.new if @start_over_component %>
30
25
  <% end %>
@@ -6,21 +6,23 @@ module Blacklight
6
6
  renders_many :facet_constraints_area
7
7
  renders_many :additional_constraints
8
8
 
9
- def self.for_search_history(**kwargs)
10
- new(tag: :span,
11
- render_headers: false,
9
+ # Constraints are stored and used to display search history - with this method, we initialize the ConstraintsComponent
10
+ # in a way that displays well in a table (and without a start-over button)
11
+ def self.for_search_history(**)
12
+ new(tag: :span, render_headers: false,
12
13
  id: nil,
13
14
  query_constraint_component: Blacklight::SearchHistoryConstraintLayoutComponent,
14
15
  facet_constraint_component_options: { layout: Blacklight::SearchHistoryConstraintLayoutComponent },
15
16
  start_over_component: nil,
16
- **kwargs)
17
+ **)
17
18
  end
18
19
 
19
20
  # rubocop:disable Metrics/ParameterLists
20
21
  def initialize(search_state:,
21
22
  tag: :div,
22
23
  render_headers: true,
23
- id: 'appliedParams', classes: 'clearfix constraints-container mb-2',
24
+ heading_classes: 'constraints-label h6 mb-0',
25
+ id: 'appliedParams', classes: 'clearfix constraints-container mb-2 align-items-center',
24
26
  query_constraint_component: Blacklight::ConstraintLayoutComponent,
25
27
  query_constraint_component_options: {},
26
28
  facet_constraint_component: Blacklight::ConstraintComponent,
@@ -33,12 +35,14 @@ module Blacklight
33
35
  @facet_constraint_component_options = facet_constraint_component_options
34
36
  @start_over_component = start_over_component
35
37
  @render_headers = render_headers
38
+ @heading_classes = heading_classes
36
39
  @tag = tag
37
40
  @id = id
38
41
  @classes = classes
39
42
  end
40
43
  # rubocop:enable Metrics/ParameterLists
41
44
 
45
+ # @return [String] HTML representation of query constraints
42
46
  def query_constraints
43
47
  if @search_state.query_param.present?
44
48
  render(
@@ -56,41 +60,54 @@ module Blacklight
56
60
  end + render(@facet_constraint_component.with_collection(clause_presenters.to_a, **@facet_constraint_component_options))
57
61
  end
58
62
 
63
+ # @return [String] URL path to remove the current query
59
64
  def remove_path
60
65
  helpers.search_action_path(@search_state.remove_query_params)
61
66
  end
62
67
 
68
+ # @return [String] HTML representation of facet constraints
63
69
  def facet_constraints
64
- render(@facet_constraint_component.with_collection(facet_item_presenters.to_a, **@facet_constraint_component_options))
70
+ render(@facet_constraint_component.with_collection(constraint_presenters.to_a, **@facet_constraint_component_options))
65
71
  end
66
72
 
73
+ # @return [Boolean] true if search state has constraints
67
74
  def render?
68
75
  @search_state.has_constraints?
69
76
  end
70
77
 
71
78
  private
72
79
 
80
+ # @return [String, nil] label for the search field if not the default search field
73
81
  def label
74
82
  search_field = @search_state.params[:search_field]
75
83
  helpers.label_for_search_field(search_field) unless helpers.default_search_field?(search_field)
76
84
  end
77
85
 
78
- def facet_item_presenters
79
- return to_enum(:facet_item_presenters) unless block_given?
86
+ # Yields constraint presenters for each facet value
87
+ #
88
+ # @yield [Blacklight::ConstraintPresenter] facet constraint presenter
89
+ # @return [Enumerator] if no block given
90
+ def constraint_presenters
91
+ return to_enum(:constraint_presenters) unless block_given?
80
92
 
81
93
  @search_state.filters.map do |facet|
94
+ facet_field_presenter = helpers.facet_field_presenter(facet.config, {})
82
95
  facet.each_value do |val|
83
96
  next if val.blank?
84
97
 
85
98
  if val.is_a?(Array)
86
- yield inclusive_facet_item_presenter(facet.config, val, facet.key) if val.any?(&:present?)
99
+ yield inclusive_facet_constraint_presenter(facet_field_presenter, facet.config, val, facet.key) if val.any?(&:present?)
87
100
  else
88
- yield facet_item_presenter(facet.config, val, facet.key)
101
+ yield facet_constraint_presenter(facet_field_presenter, facet.config, val)
89
102
  end
90
103
  end
91
104
  end
92
105
  end
93
106
 
107
+ # Yields clause presenters for search clauses
108
+ #
109
+ # @yield [Blacklight::ClausePresenter] clause presenter
110
+ # @return [Enumerator] if no block given
94
111
  def clause_presenters
95
112
  return to_enum(:clause_presenters) unless block_given?
96
113
 
@@ -100,12 +117,40 @@ module Blacklight
100
117
  end
101
118
  end
102
119
 
103
- def facet_item_presenter(facet_config, facet_item, facet_field)
104
- facet_config.item_presenter.new(facet_item, facet_config, helpers, facet_field)
120
+ # Creates a facet constraint presenter for a single facet item
121
+ #
122
+ # @param facet_field_presenter [Blacklight::FacetFieldPresenter] presenter for the facet field
123
+ # @param facet_config [Blacklight::Configuration::FacetField] configuration for the facet
124
+ # @param facet_item [String] the facet item
125
+ # @return [Blacklight::ConstraintPresenter] constraint presenter for the facet item
126
+ def facet_constraint_presenter(facet_field_presenter, facet_config, facet_item)
127
+ facet_config.constraint_presenter.new(facet_item_presenter: facet_field_presenter.item_presenter(facet_item), field_label: facet_field_presenter.label)
105
128
  end
106
129
 
107
- def inclusive_facet_item_presenter(facet_config, facet_item, facet_field)
108
- Blacklight::InclusiveFacetItemPresenter.new(facet_item, facet_config, helpers, facet_field)
130
+ # Creates a constraint presenter for an inclusive facet (multiple values)
131
+ #
132
+ # @param facet_field_presenter [Blacklight::FacetFieldPresenter] presenter for the facet field
133
+ # @param facet_config [Blacklight::Configuration::FacetField] configuration for the facet
134
+ # @param facet_item [Array] array of facet items
135
+ # @param facet_field [Symbol, String] the facet field name
136
+ # @return [Blacklight::ConstraintPresenter] constraint presenter for the inclusive facet
137
+ def inclusive_facet_constraint_presenter(facet_field_presenter, facet_config, facet_item, facet_field)
138
+ facet_config.constraint_presenter.new(
139
+ facet_item_presenter: Blacklight::InclusiveFacetItemPresenter.new(facet_item, facet_config, helpers, facet_field),
140
+ field_label: facet_field_presenter.label
141
+ )
142
+ end
143
+
144
+ # Returns a heading tag for the constraints section
145
+ #
146
+ # @return [ActiveSupport::SafeBuffer, nil] constraints heading html
147
+ def constraints_heading
148
+ return unless @render_headers
149
+
150
+ tag.h2(
151
+ t('blacklight.search.filters.title'),
152
+ class: @heading_classes
153
+ )
109
154
  end
110
155
  end
111
156
  end
@@ -61,9 +61,7 @@ module Blacklight
61
61
  end
62
62
  end
63
63
 
64
- def key
65
- @action.key
66
- end
64
+ delegate :key, to: :@action
67
65
  end
68
66
  end
69
67
  end
@@ -1,7 +1,7 @@
1
1
  <%- # we don't use the per-form csrf token -%>
2
2
  <%= form_tag(bookmark_path,
3
3
  authenticity_token: false,
4
- method: bookmarked? ? :delete : :put,
4
+ method: bookmarked? ? :delete : :put,
5
5
  class: "bookmark-toggle",
6
6
  data: {
7
7
  present: t('blacklight.search.bookmarks.present'),
@@ -9,8 +9,8 @@
9
9
  inprogress: t('blacklight.search.bookmarks.inprogress')
10
10
  }) do %>
11
11
  <div class="toggle-bookmark">
12
- <label class="toggle-bookmark-label" data-checkboxsubmit-target="label">
13
- <input type="checkbox" class="toggle-bookmark-input <%= bookmark_icon ? 'd-none' : '' %>" data-checkboxsubmit-target="checkbox" <%= 'checked="checked"' if bookmarked? %>>
12
+ <label class="toggle-bookmark-label" data-checkboxsubmit-target="label" <% if bookmark_icon %>tabindex="0"<% end %>>
13
+ <input type="checkbox" class="toggle-bookmark-input <%= bookmark_icon ? 'd-none' : '' %>" data-checkboxsubmit-target="checkbox" <%= 'checked=checked' if bookmarked? %>>
14
14
  <%= bookmark_icon %>
15
15
  <span data-checkboxsubmit-target="span"><%= bookmarked? ? t('blacklight.search.bookmarks.present') : t('blacklight.search.bookmarks.absent') %></span>
16
16
  </label>
@@ -3,16 +3,22 @@
3
3
  module Blacklight
4
4
  module Document
5
5
  # Render a bookmark widget to bookmark / unbookmark a document
6
- class BookmarkComponent < Blacklight::Document::ActionComponent
6
+ class BookmarkComponent < Blacklight::Component
7
7
  # @param [Blacklight::Document] document
8
- # @param [Blacklight::Configuration::ToolConfig] action
8
+ # @param [Blacklight::Configuration::ToolConfig] action - only used to pass a key for the wrapping action.
9
9
  # @param [Boolean] checked
10
10
  # @param [Object] bookmark_path the rails route to use for bookmarks
11
- def initialize(document:, action: nil, checked: nil, bookmark_path: nil, **kwargs)
11
+ def initialize(document:, action: nil, checked: nil, bookmark_path: nil, **)
12
12
  @document = document
13
13
  @checked = checked
14
14
  @bookmark_path = bookmark_path
15
- super(document: document, action: action, **kwargs)
15
+ @action = action
16
+ super()
17
+ end
18
+
19
+ # Used by ActionsComponent
20
+ def key
21
+ @action&.key || :bookmark
16
22
  end
17
23
 
18
24
  def bookmarked?
@@ -4,6 +4,6 @@
4
4
  <%= grouped_documents %>
5
5
  </div>
6
6
  <%- if @group_limit > 0 && @group.total > @group_limit %>
7
- <%= helpers.link_to t('blacklight.search.group.more'), add_group_facet_params_and_redirect(@group), class: 'more-in-group float-right' %>
7
+ <%= helpers.link_to t('blacklight.search.group.more'), add_group_facet_params_and_redirect(@group), class: 'more-in-group float-end' %>
8
8
  <%- end %>
9
9
  </div>
@@ -15,8 +15,8 @@ module Blacklight
15
15
  @document.more_like_this.present?
16
16
  end
17
17
 
18
- def link_to_document(*args)
19
- helpers.link_to_document(*args)
18
+ def link_to_document(*)
19
+ helpers.link_to_document(*)
20
20
  end
21
21
  end
22
22
  end
@@ -4,12 +4,12 @@ module Blacklight
4
4
  module Document
5
5
  # Render the start over and prev/next displays
6
6
  class PageHeaderComponent < Blacklight::Component
7
- attr_reader :document, :blacklight_config, :search_context, :search_session
7
+ attr_reader :document, :search_context, :search_session
8
8
 
9
9
  delegate :blacklight_config, to: :helpers
10
10
 
11
11
  def initialize(document:, search_context:, search_session:)
12
- super
12
+ super()
13
13
  @search_context = search_context
14
14
  @search_session = search_session
15
15
  @document = document
@@ -40,7 +40,7 @@ module Blacklight
40
40
  end
41
41
 
42
42
  def header_container_classes
43
- has_header_tools? ? 'row pagination-search-widgets pb-3' : 'pagination-search-widgets pb-3'
43
+ has_header_tools? ? 'row pagination-search-widgets pb-3 mb-3' : 'pagination-search-widgets pb-3 mb-3'
44
44
  end
45
45
 
46
46
  def header_actions
@@ -1,7 +1,3 @@
1
- <% value = presenter.thumbnail.render(@image_options) %>
2
-
3
- <% if value %>
4
- <div class="document-thumbnail">
5
- <%= helpers.link_to_document(presenter.document, value, 'aria-hidden': true, tabindex: -1, counter: @counter) %>
6
- </div>
7
- <% end %>
1
+ <div class="document-thumbnail">
2
+ <%= helpers.link_to_document(presenter.document, thumbnail_value, 'aria-hidden': true, tabindex: -1, counter: @counter) %>
3
+ </div>
@@ -9,19 +9,20 @@ module Blacklight
9
9
  # @param [Blacklight::DocumentPresenter] presenter
10
10
  # @param [Integer] counter
11
11
  # @param [Hash] image_options options for the thumbnail presenter's image tag
12
- def initialize(counter:, presenter: nil, document: nil, image_options: {})
12
+ def initialize(counter:, presenter: nil, image_options: {})
13
13
  @presenter = presenter
14
- @document = presenter&.document || document
15
14
  @counter = counter
16
15
  @image_options = { alt: '' }.merge(image_options)
17
16
  end
18
17
 
19
- def render?
20
- presenter.thumbnail.exists?
18
+ attr_accessor :presenter
19
+
20
+ def thumbnail_value
21
+ @thumbnail_value ||= presenter.thumbnail.render(@image_options)
21
22
  end
22
23
 
23
- def presenter
24
- @presenter ||= helpers.document_presenter(@document)
24
+ def render?
25
+ presenter.thumbnail && thumbnail_value
25
26
  end
26
27
  end
27
28
  end
@@ -1,11 +1,11 @@
1
1
  <%= content_tag @component,
2
2
  id: @id,
3
3
  data: {
4
- 'document-id': @document.id.to_s.parameterize,
5
- 'document-counter': @counter,
4
+ 'document-id': document.id.to_s.parameterize,
5
+ 'document-counter': counter,
6
6
  },
7
7
  itemscope: true,
8
- itemtype: @document.itemtype,
8
+ itemtype: document.itemtype,
9
9
  class: classes.flatten.join(' ') do %>
10
10
  <%= header %>
11
11
  <% if body.present? %>
@@ -33,40 +33,36 @@ module Blacklight
33
33
  renders_one :body
34
34
 
35
35
  # The document title with some reasonable default behavior
36
- renders_one :title, (lambda do |*args, component: nil, **kwargs|
37
- component ||= view_config.title_component || Blacklight::DocumentTitleComponent
36
+ renders_one :title, (lambda do |component: nil, **kwargs|
37
+ component ||= view_config.document_title_component
38
38
 
39
- component.new(*args, counter: @counter, document: @document, presenter: @presenter, as: @title_component, actions: !@show, link_to_document: !@show, document_component: self, **kwargs)
39
+ component&.new(counter: @counter, presenter: @presenter, as: @title_component, actions: !@show, link_to_document: !@show, document_component: self, **kwargs)
40
40
  end)
41
41
 
42
- renders_one :embed, (lambda do |static_content = nil, *args, component: nil, **kwargs|
42
+ renders_one :embed, (lambda do |static_content = nil, component: nil, **kwargs|
43
43
  next static_content if static_content.present?
44
44
 
45
- component ||= view_config.embed_component
46
-
47
- next unless component
48
-
49
- component.new(*args, document: @document, presenter: @presenter, document_counter: @document_counter, **kwargs)
45
+ component ||= view_config.document_embed_component
46
+ component&.new(presenter: @presenter, document_counter: @document_counter, **kwargs)
50
47
  end)
51
48
 
52
49
  # The primary metadata section
53
- renders_one :metadata, (lambda do |static_content = nil, *args, component: nil, fields: nil, **kwargs|
50
+ renders_one :metadata, (lambda do |static_content = nil, component: nil, fields: nil, **kwargs|
54
51
  next static_content if static_content.present?
55
52
 
56
- component ||= view_config.metadata_component || Blacklight::DocumentMetadataComponent
57
-
58
- component.new(*args, fields: fields || @presenter&.field_presenters || [], **kwargs)
53
+ component ||= view_config.document_metadata_component
54
+ component&.new(fields: fields || @presenter&.field_presenters || [], **kwargs)
59
55
  end)
60
56
 
61
57
  # Additional metadata sections
62
58
  renders_many :metadata_sections
63
59
 
64
- renders_one :thumbnail, (lambda do |image_options_or_static_content = {}, *args, component: nil, **kwargs|
60
+ renders_one :thumbnail, (lambda do |image_options_or_static_content = {}, component: nil, **kwargs|
65
61
  next image_options_or_static_content if image_options_or_static_content.is_a? String
66
62
 
67
- component ||= view_config.thumbnail_component || Blacklight::Document::ThumbnailComponent
63
+ component ||= view_config.document_thumbnail_component
68
64
 
69
- component.new(*args, document: @document, presenter: @presenter, counter: @counter, image_options: image_options_or_static_content, **kwargs)
65
+ component&.new(presenter: @presenter, counter: @counter, image_options: image_options_or_static_content, **kwargs)
70
66
  end)
71
67
 
72
68
  # A container for partials rendered using the view config partials configuration. Its use is discouraged, but necessary until
@@ -90,18 +86,18 @@ module Blacklight
90
86
  def initialize(document: nil, partials: nil,
91
87
  id: nil, classes: [], component: :article, title_component: nil,
92
88
  counter: nil, document_counter: nil, counter_offset: 0,
93
- show: false, **args)
94
- @presenter = document || args[self.class.collection_parameter]
89
+ show: false)
90
+ @presenter = document
95
91
  @document = @presenter.document
96
92
  @view_partials = partials || []
97
93
 
98
94
  @component = component
99
95
  @title_component = title_component
100
- @id = id || ('document' if show)
96
+ @id = id
101
97
  @classes = classes
102
98
 
103
99
  @counter = counter
104
- @document_counter = document_counter || args.fetch(self.class.collection_counter_parameter, nil)
100
+ @document_counter = document_counter
105
101
  @counter ||= 1 + @document_counter + counter_offset if @document_counter.present?
106
102
 
107
103
  @show = show
@@ -119,14 +115,14 @@ module Blacklight
119
115
  end
120
116
 
121
117
  def before_render
122
- set_slot(:title, nil) unless title
123
- set_slot(:thumbnail, nil) unless thumbnail || show?
124
- set_slot(:metadata, nil, fields: presenter.field_presenters, show: @show) unless metadata
125
- set_slot(:embed, nil) unless embed
118
+ with_title unless title
119
+ with_thumbnail unless thumbnail
120
+ with_metadata(fields: presenter.field_presenters, show: @show) unless metadata
121
+ with_embed unless embed
126
122
 
127
123
  view_partials.each do |view_partial|
128
124
  with_partial(view_partial) do
129
- helpers.render_document_partial @document, view_partial, component: self, document_counter: @counter
125
+ helpers.render_document_partial document, view_partial, component: self, document_counter: counter
130
126
  end
131
127
  end
132
128
  end
@@ -135,7 +131,7 @@ module Blacklight
135
131
 
136
132
  delegate :view_config, to: :@presenter
137
133
 
138
- attr_reader :document_counter, :presenter, :view_partials
134
+ attr_reader :document_counter, :counter, :document, :presenter, :view_partials
139
135
 
140
136
  def show?
141
137
  @show
@@ -7,12 +7,9 @@ module Blacklight
7
7
  renders_many :actions
8
8
 
9
9
  # rubocop:disable Metrics/ParameterLists
10
- def initialize(title = nil, document: nil, presenter: nil, as: :h3, counter: nil, classes: 'index_title document-title-heading col h5', link_to_document: true, document_component: nil,
10
+ def initialize(title = nil, presenter:, as: :h3, counter: nil, classes: 'index_title document-title-heading col h5', link_to_document: true, document_component: nil,
11
11
  actions: true)
12
- raise ArgumentError, 'missing keyword: :document or :presenter' if presenter.nil? && document.nil?
13
-
14
12
  @title = title
15
- @document = document
16
13
  @presenter = presenter
17
14
  @as = as || :h3
18
15
  @counter = counter
@@ -20,9 +17,14 @@ module Blacklight
20
17
  @link_to_document = link_to_document
21
18
  @document_component = document_component
22
19
  @actions = actions
20
+ @document = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(@presenter.document,
21
+ "Don't use the @document instance variable. Instead use @presenter",
22
+ ActiveSupport::Deprecation.new)
23
23
  end
24
24
  # rubocop:enable Metrics/ParameterLists
25
25
 
26
+ attr_accessor :presenter
27
+
26
28
  # Content for the document title area; should be an inline element
27
29
  def title
28
30
  if @link_to_document
@@ -53,11 +55,5 @@ module Blacklight
53
55
  t('blacklight.search.documents.counter', counter: @counter)
54
56
  end
55
57
  end
56
-
57
- private
58
-
59
- def presenter
60
- @presenter ||= helpers.document_presenter(@document)
61
- end
62
58
  end
63
59
  end
@@ -1,24 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Blacklight
4
- class FacetFieldCheckboxesComponent < Blacklight::Component
5
- def initialize(facet_field:, layout: nil)
6
- @facet_field = facet_field
7
- @layout = layout == false ? FacetFieldNoLayoutComponent : Blacklight::FacetFieldComponent
8
- end
9
-
10
- def render?
11
- presenters.any?
12
- end
13
-
14
- def presenters
15
- return [] unless @facet_field.paginator
16
-
17
- return to_enum(:presenters) unless block_given?
18
-
19
- @facet_field.paginator.items.each do |item|
20
- yield Blacklight::FacetCheckboxItemPresenter.new(item, @facet_field.facet_field, helpers, @facet_field.key, @facet_field.search_state)
21
- end
4
+ class FacetFieldCheckboxesComponent < Facets::CheckboxesComponent
5
+ def initialize(...)
6
+ Rails.logger.warn("Blacklight::FacetFieldCheckboxesComponent is deprecated. Use Blacklight::Facets::CheckboxesComponent instead.")
7
+ super
22
8
  end
23
9
  end
24
10
  end