blacklight 8.11.0 → 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 (288) hide show
  1. checksums.yaml +4 -4
  2. data/.env +3 -3
  3. data/.github/matrix.json +11 -42
  4. data/.github/pull_request_template.md +7 -0
  5. data/.github/workflows/main.yml +0 -2
  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 +0 -5
  9. data/.rubocop.yml +71 -3
  10. data/.rubocop_todo.yml +43 -76
  11. data/.solr_wrapper.yml +2 -0
  12. data/README.md +30 -8
  13. data/VERSION +1 -1
  14. data/app/assets/builds/blacklight.css +452 -0
  15. data/app/assets/javascripts/blacklight/blacklight.esm.js +6 -76
  16. data/app/assets/javascripts/blacklight/blacklight.esm.js.map +1 -1
  17. data/app/assets/javascripts/blacklight/blacklight.js +6 -76
  18. data/app/assets/javascripts/blacklight/blacklight.js.map +1 -1
  19. data/app/assets/stylesheets/blacklight/_balanced_list.scss +1 -4
  20. data/app/assets/stylesheets/blacklight/_blacklight_base.scss +1 -3
  21. data/app/assets/stylesheets/blacklight/_bookmark.scss +44 -41
  22. data/app/assets/stylesheets/blacklight/_bootstrap_overrides.scss +0 -25
  23. data/app/assets/stylesheets/blacklight/_constraints.scss +15 -24
  24. data/app/assets/stylesheets/blacklight/_controls.scss +2 -18
  25. data/app/assets/stylesheets/blacklight/_facets.scss +17 -84
  26. data/app/assets/stylesheets/blacklight/_group.scss +2 -5
  27. data/app/assets/stylesheets/blacklight/_header.scss +8 -11
  28. data/app/assets/stylesheets/blacklight/_icons.scss +0 -8
  29. data/app/assets/stylesheets/blacklight/_modal.scss +1 -1
  30. data/app/assets/stylesheets/blacklight/_pagination.scss +0 -4
  31. data/app/assets/stylesheets/blacklight/_search_form.scss +0 -1
  32. data/app/assets/stylesheets/blacklight/_search_history.scss +0 -8
  33. data/app/assets/stylesheets/blacklight/_search_results.scss +1 -15
  34. data/app/assets/stylesheets/blacklight/blacklight_defaults.scss +9 -14
  35. data/app/assets/stylesheets/blacklight/build.scss +4 -0
  36. data/app/components/blacklight/advanced_search_form_component.rb +3 -3
  37. data/app/components/blacklight/constraint_component.rb +1 -1
  38. data/app/components/blacklight/constraint_layout_component.html.erb +2 -2
  39. data/app/components/blacklight/constraints_component.html.erb +2 -2
  40. data/app/components/blacklight/constraints_component.rb +3 -3
  41. data/app/components/blacklight/document/bookmark_component.html.erb +3 -3
  42. data/app/components/blacklight/document/bookmark_component.rb +2 -2
  43. data/app/components/blacklight/document/group_component.html.erb +1 -1
  44. data/app/components/blacklight/document/more_like_this_component.rb +2 -2
  45. data/app/components/blacklight/document/page_header_component.rb +1 -1
  46. data/app/components/blacklight/document/sidebar_component.rb +5 -5
  47. data/app/components/blacklight/document/thumbnail_component.html.erb +3 -7
  48. data/app/components/blacklight/document/thumbnail_component.rb +7 -6
  49. data/app/components/blacklight/document_component.rb +12 -16
  50. data/app/components/blacklight/document_title_component.rb +5 -11
  51. data/app/components/blacklight/facet_field_checkboxes_component.rb +2 -20
  52. data/app/components/blacklight/facet_field_component.rb +2 -17
  53. data/app/components/blacklight/facet_field_filter_component.rb +2 -21
  54. data/app/components/blacklight/facet_field_inclusive_constraint_component.rb +4 -25
  55. data/app/components/blacklight/facet_field_list_component.rb +2 -50
  56. data/app/components/blacklight/facet_field_no_layout_component.rb +2 -10
  57. data/app/components/blacklight/facet_item_component.rb +2 -74
  58. data/app/components/blacklight/facet_item_pivot_component.rb +3 -3
  59. data/app/components/blacklight/facets/checkboxes_component.rb +26 -0
  60. data/app/components/blacklight/facets/count_component.rb +23 -0
  61. data/app/components/blacklight/{facet_field_component.html.erb → facets/field_component.html.erb} +4 -4
  62. data/app/components/blacklight/facets/field_component.rb +23 -0
  63. data/app/components/blacklight/facets/filters_component.html.erb +4 -0
  64. data/app/components/blacklight/facets/filters_component.rb +27 -0
  65. data/app/components/blacklight/{facet_field_inclusive_constraint_component.html.erb → facets/inclusive_constraint_component.html.erb} +1 -1
  66. data/app/components/blacklight/facets/inclusive_constraint_component.rb +31 -0
  67. data/app/components/blacklight/{facet_field_filter_component.html.erb → facets/index_navigation_component.html.erb} +1 -1
  68. data/app/components/blacklight/facets/index_navigation_component.rb +32 -0
  69. data/app/components/blacklight/facets/item_component.rb +73 -0
  70. data/app/components/blacklight/facets/list_component.html.erb +11 -0
  71. data/app/components/blacklight/facets/list_component.rb +38 -0
  72. data/app/components/blacklight/facets/no_layout_component.rb +16 -0
  73. data/app/components/blacklight/facets/selected_value_component.rb +29 -0
  74. data/app/components/blacklight/facets/suggest_component.html.erb +12 -0
  75. data/app/components/blacklight/facets/suggest_component.rb +22 -0
  76. data/app/components/blacklight/metadata_field_plain_text_layout_component.rb +2 -2
  77. data/app/components/blacklight/response/facet_group_component.html.erb +3 -18
  78. data/app/components/blacklight/response/facet_group_component.rb +11 -23
  79. data/app/components/blacklight/response/facet_toggle_button_component.html.erb +16 -0
  80. data/app/components/blacklight/response/facet_toggle_button_component.rb +14 -0
  81. data/app/components/blacklight/response/pagination_component.html.erb +1 -1
  82. data/app/components/blacklight/response/pagination_component.rb +2 -1
  83. data/app/components/blacklight/response/sort_component.rb +1 -0
  84. data/app/components/blacklight/response/view_type_button_component.html.erb +1 -1
  85. data/app/components/blacklight/response/view_type_component.html.erb +1 -1
  86. data/app/components/blacklight/search/per_page_component.html.erb +1 -1
  87. data/app/components/blacklight/search/per_page_component.rb +1 -0
  88. data/app/components/blacklight/search/sidebar_component.html.erb +1 -1
  89. data/app/components/blacklight/search/sidebar_component.rb +1 -1
  90. data/app/components/blacklight/search_bar_component.html.erb +3 -3
  91. data/app/components/blacklight/search_bar_component.rb +2 -2
  92. data/app/components/blacklight/search_button_component.rb +2 -2
  93. data/app/components/blacklight/search_context/server_applied_params_component.html.erb +2 -2
  94. data/app/components/blacklight/search_context/server_applied_params_component.rb +9 -0
  95. data/app/components/blacklight/skip_link_component.html.erb +1 -1
  96. data/app/components/blacklight/skip_link_component.rb +2 -1
  97. data/app/components/blacklight/top_navbar_component.html.erb +2 -2
  98. data/app/controllers/concerns/blacklight/bookmarks.rb +3 -3
  99. data/app/controllers/concerns/blacklight/catalog.rb +9 -23
  100. data/app/controllers/concerns/blacklight/controller.rb +1 -1
  101. data/app/controllers/concerns/blacklight/facetable.rb +34 -0
  102. data/app/controllers/concerns/blacklight/search_context.rb +0 -12
  103. data/app/controllers/concerns/blacklight/searchable.rb +1 -1
  104. data/app/helpers/blacklight/blacklight_helper_behavior.rb +0 -6
  105. data/app/helpers/blacklight/catalog_helper_behavior.rb +0 -10
  106. data/app/helpers/blacklight/configuration_helper_behavior.rb +2 -14
  107. data/app/helpers/blacklight/document_helper_behavior.rb +3 -27
  108. data/app/helpers/blacklight/facets_helper_behavior.rb +9 -0
  109. data/app/helpers/blacklight/icon_helper_behavior.rb +3 -11
  110. data/app/helpers/blacklight/layout_helper_behavior.rb +2 -2
  111. data/app/helpers/blacklight/render_partials_helper_behavior.rb +0 -14
  112. data/app/helpers/blacklight/url_helper_behavior.rb +1 -1
  113. data/app/javascript/{blacklight → blacklight-frontend}/bookmark_toggle.js +1 -1
  114. data/app/javascript/{blacklight → blacklight-frontend}/checkbox_submit.js +3 -0
  115. data/app/javascript/{blacklight → blacklight-frontend}/core.js +2 -10
  116. data/app/javascript/{blacklight → blacklight-frontend}/facet_suggest.js +1 -3
  117. data/app/javascript/blacklight-frontend/index.js +16 -0
  118. data/app/javascript/{blacklight → blacklight-frontend}/modal.js +1 -5
  119. data/app/models/concerns/blacklight/document.rb +0 -11
  120. data/app/models/concerns/blacklight/user.rb +1 -1
  121. data/app/models/facet_search_builder.rb +5 -0
  122. data/app/presenters/blacklight/facet_field_presenter.rb +3 -3
  123. data/app/presenters/blacklight/rendering/helper_method.rb +4 -4
  124. data/app/presenters/blacklight/rendering/join.rb +2 -2
  125. data/app/services/blacklight/facet_search_service.rb +44 -0
  126. data/app/services/blacklight/field_retriever.rb +1 -1
  127. data/app/services/blacklight/search_params_yaml_coder.rb +0 -2
  128. data/app/services/blacklight/search_service.rb +6 -6
  129. data/app/values/blacklight/types.rb +2 -2
  130. data/app/views/bookmarks/_clear_bookmarks_widget.html.erb +0 -2
  131. data/app/views/bookmarks/index.html.erb +1 -1
  132. data/app/views/catalog/_facet_pivot.html.erb +1 -1
  133. data/app/views/catalog/_home_text.html.erb +2 -2
  134. data/app/views/catalog/_results_pagination.html.erb +2 -5
  135. data/app/views/catalog/_search_results.html.erb +3 -3
  136. data/app/views/catalog/_search_results_header.html.erb +1 -1
  137. data/app/views/catalog/_sort_and_per_page.html.erb +1 -1
  138. data/app/views/catalog/_sort_widget.html.erb +1 -0
  139. data/app/views/catalog/facet.html.erb +4 -6
  140. data/app/views/catalog/show.html.erb +2 -3
  141. data/app/views/kaminari/blacklight/_paginator.html.erb +1 -2
  142. data/app/views/layouts/blacklight/base.html.erb +3 -7
  143. data/app/views/search_history/index.html.erb +0 -2
  144. data/blacklight.gemspec +4 -4
  145. data/config/importmap.rb +1 -1
  146. data/config/locales/blacklight.ar.yml +2 -2
  147. data/config/locales/blacklight.ca.yml +124 -124
  148. data/config/locales/blacklight.de.yml +2 -2
  149. data/config/locales/blacklight.en.yml +14 -14
  150. data/config/locales/blacklight.es.yml +2 -2
  151. data/config/locales/blacklight.fr.yml +2 -2
  152. data/config/locales/blacklight.hu.yml +2 -2
  153. data/config/locales/blacklight.it.yml +1 -1
  154. data/config/locales/blacklight.nl.yml +2 -2
  155. data/config/locales/blacklight.pt-BR.yml +1 -1
  156. data/config/locales/blacklight.sq.yml +2 -2
  157. data/config/locales/blacklight.zh.yml +2 -2
  158. data/lib/blacklight/abstract_repository.rb +2 -2
  159. data/lib/blacklight/abstract_search_builder.rb +154 -0
  160. data/lib/blacklight/configuration/context.rb +3 -3
  161. data/lib/blacklight/configuration/display_field.rb +1 -1
  162. data/lib/blacklight/configuration/facet_field.rb +6 -6
  163. data/lib/blacklight/configuration/field.rb +4 -4
  164. data/lib/blacklight/configuration/fields.rb +3 -4
  165. data/lib/blacklight/configuration/search_field.rb +1 -1
  166. data/lib/blacklight/configuration/view_config.rb +2 -4
  167. data/lib/blacklight/configuration.rb +11 -18
  168. data/lib/blacklight/engine.rb +0 -6
  169. data/lib/blacklight/facet_search_builder.rb +18 -0
  170. data/lib/blacklight/nested_open_struct_with_hash_access.rb +1 -1
  171. data/lib/blacklight/open_struct_with_hash_access.rb +5 -5
  172. data/lib/blacklight/search_builder.rb +1 -159
  173. data/lib/blacklight/search_state/filter_field.rb +2 -2
  174. data/lib/blacklight/search_state/pivot_filter_field.rb +4 -4
  175. data/lib/blacklight/solr/abstract_filter_query_builder.rb +77 -0
  176. data/lib/blacklight/solr/default_filter_query_builder.rb +20 -0
  177. data/lib/blacklight/solr/facet_search_builder_behavior.rb +62 -0
  178. data/lib/blacklight/solr/repository.rb +8 -9
  179. data/lib/blacklight/solr/request.rb +1 -7
  180. data/lib/blacklight/solr/response/facets.rb +2 -2
  181. data/lib/blacklight/solr/response/group_response.rb +2 -2
  182. data/lib/blacklight/solr/response/params.rb +0 -4
  183. data/lib/blacklight/solr/response.rb +5 -1
  184. data/lib/blacklight/solr/search_builder_behavior.rb +17 -132
  185. data/lib/blacklight.rb +2 -2
  186. data/lib/generators/blacklight/assets/importmap_generator.rb +6 -24
  187. data/lib/generators/blacklight/assets/propshaft_generator.rb +1 -1
  188. data/lib/generators/blacklight/assets_generator.rb +3 -3
  189. data/lib/generators/blacklight/controller_generator.rb +3 -3
  190. data/lib/generators/blacklight/search_builder_generator.rb +1 -1
  191. data/lib/generators/blacklight/templates/.solr_wrapper.yml +2 -0
  192. data/lib/generators/blacklight/templates/catalog_controller.rb +3 -1
  193. data/lib/generators/blacklight/templates/solr/conf/solrconfig.xml +0 -4
  194. data/lib/generators/blacklight/user_generator.rb +9 -10
  195. data/package.json +15 -5
  196. data/rollup.config.js +1 -1
  197. data/spec/components/blacklight/advanced_search_form_component_spec.rb +18 -22
  198. data/spec/components/blacklight/constraint_layout_component_spec.rb +8 -8
  199. data/spec/components/blacklight/constraints_component_spec.rb +11 -11
  200. data/spec/components/blacklight/document/action_component_spec.rb +21 -17
  201. data/spec/components/blacklight/document/group_component_spec.rb +10 -15
  202. data/spec/components/blacklight/document/page_header_component_spec.rb +35 -28
  203. data/spec/components/blacklight/document/sidebar_component_spec.rb +9 -30
  204. data/spec/components/blacklight/document_component_spec.rb +98 -65
  205. data/spec/components/blacklight/facet_component_spec.rb +12 -8
  206. data/spec/components/blacklight/facet_item_pivot_component_spec.rb +12 -12
  207. data/spec/components/blacklight/{facet_field_checkboxes_component_spec.rb → facets/checkboxes_component_spec.rb} +14 -14
  208. data/spec/components/blacklight/facets/filters_component_spec.rb +36 -0
  209. data/spec/components/blacklight/facets/index_navigation_component_spec.rb +40 -0
  210. data/spec/components/blacklight/{facet_item_component_spec.rb → facets/item_component_spec.rb} +10 -10
  211. data/spec/components/blacklight/{facet_field_list_component_spec.rb → facets/list_component_spec.rb} +24 -24
  212. data/spec/components/blacklight/facets/suggest_component_spec.rb +68 -0
  213. data/spec/components/blacklight/header_component_spec.rb +2 -4
  214. data/spec/components/blacklight/hidden_search_state_component_spec.rb +7 -7
  215. data/spec/components/blacklight/metadata_field_component_spec.rb +17 -15
  216. data/spec/components/blacklight/response/facet_group_component_spec.rb +37 -0
  217. data/spec/components/blacklight/response/pagination_component_spec.rb +1 -1
  218. data/spec/components/blacklight/response/spellcheck_component_spec.rb +1 -1
  219. data/spec/components/blacklight/search_bar_component_spec.rb +5 -5
  220. data/spec/components/blacklight/search_context/server_applied_params_component_spec.rb +2 -2
  221. data/spec/components/blacklight/search_context/server_item_pagination_component_spec.rb +3 -5
  222. data/spec/components/blacklight/skip_link_component_spec.rb +8 -11
  223. data/spec/components/blacklight/start_over_button_component_spec.rb +4 -4
  224. data/spec/components/blacklight/system/flash_message_component_spec.rb +7 -11
  225. data/spec/controllers/catalog_controller_spec.rb +11 -19
  226. data/spec/features/axe_spec.rb +6 -11
  227. data/spec/features/bookmarks_spec.rb +48 -11
  228. data/spec/features/facets_spec.rb +58 -63
  229. data/spec/features/search_context_spec.rb +1 -2
  230. data/spec/features/search_filters_spec.rb +6 -6
  231. data/spec/helpers/blacklight/configuration_helper_behavior_spec.rb +0 -9
  232. data/spec/helpers/blacklight/facets_helper_behavior_spec.rb +10 -0
  233. data/spec/helpers/blacklight/render_partials_helper_behavior_spec.rb +1 -1
  234. data/spec/lib/blacklight/configuration/facet_field_spec.rb +2 -2
  235. data/spec/models/blacklight/configuration_spec.rb +32 -28
  236. data/spec/models/blacklight/facet_search_builder_spec.rb +19 -0
  237. data/spec/models/blacklight/search_builder_spec.rb +1 -11
  238. data/spec/models/blacklight/solr/default_filter_query_builder_spec.rb +72 -0
  239. data/spec/models/blacklight/solr/document_spec.rb +0 -4
  240. data/spec/models/blacklight/solr/facet_search_builder_behavior_spec.rb +929 -0
  241. data/spec/models/blacklight/solr/repository_spec.rb +31 -29
  242. data/spec/models/blacklight/solr/request_spec.rb +7 -0
  243. data/spec/models/blacklight/solr/response/facets_spec.rb +86 -40
  244. data/spec/models/blacklight/solr/response/group_response_spec.rb +8 -5
  245. data/spec/models/blacklight/solr/response/group_spec.rb +9 -5
  246. data/spec/models/blacklight/solr/response_spec.rb +96 -64
  247. data/spec/models/blacklight/solr/search_builder_behavior_spec.rb +2 -227
  248. data/spec/models/solr_document_spec.rb +5 -1
  249. data/spec/services/blacklight/search_service_spec.rb +5 -26
  250. data/spec/spec_helper.rb +0 -1
  251. data/spec/support/view_component_test_helpers.rb +0 -18
  252. data/spec/views/catalog/facet.html.erb_spec.rb +10 -11
  253. data/spec/views/catalog/index.atom.builder_spec.rb +6 -3
  254. data/spec/views/catalog/index.html.erb_spec.rb +8 -3
  255. data/spec/views/catalog/show.html.erb_spec.rb +1 -0
  256. data/tasks/blacklight.rake +8 -5
  257. metadata +76 -81
  258. data/app/assets/stylesheets/blacklight/_autocomplete.scss +0 -25
  259. data/app/assets/stylesheets/blacklight/_mixins.scss +0 -20
  260. data/app/components/blacklight/facet_field_list_component.html.erb +0 -19
  261. data/app/components/blacklight/icons/legacy_icon_component.rb +0 -30
  262. data/app/components/blacklight/search/facet_suggest_input.html.erb +0 -12
  263. data/app/components/blacklight/search/facet_suggest_input.rb +0 -20
  264. data/app/javascript/blacklight/index.js +0 -18
  265. data/app/javascript/blacklight/modalForm.js +0 -60
  266. data/app/views/catalog/_constraints.html.erb +0 -1
  267. data/app/views/catalog/_facet_index_navigation.html.erb +0 -1
  268. data/app/views/catalog/_facet_layout.html.erb +0 -8
  269. data/app/views/catalog/_facet_pagination.html.erb +0 -1
  270. data/app/views/catalog/_facets.html.erb +0 -5
  271. data/app/views/catalog/_search_form.html.erb +0 -7
  272. data/app/views/catalog/_search_header.html.erb +0 -1
  273. data/app/views/catalog/_show_sidebar.html.erb +0 -3
  274. data/app/views/catalog/_show_tools.html.erb +0 -2
  275. data/app/views/catalog/_start_over.html.erb +0 -1
  276. data/app/views/shared/_header_navbar.html.erb +0 -1
  277. data/lib/generators/blacklight/assets/sprockets_generator.rb +0 -68
  278. data/spec/components/blacklight/document_metadata_component_spec.rb +0 -0
  279. data/spec/components/blacklight/search/facet_suggest_input_spec.rb +0 -57
  280. data/spec/views/catalog/_facet_index_navigation.html.erb_spec.rb +0 -43
  281. data/spec/views/catalog/_facet_layout.html.erb_spec.rb +0 -41
  282. data/spec/views/catalog/_search_header.erb_spec.rb +0 -14
  283. data/spec/views/catalog/_show_sidebar.erb_spec.rb +0 -24
  284. data/spec/views/catalog/_show_tools.html.erb_spec.rb +0 -37
  285. /data/app/components/blacklight/{facet_field_checkboxes_component.html.erb → facets/checkboxes_component.html.erb} +0 -0
  286. /data/app/javascript/{blacklight → blacklight-frontend}/button_focus.js +0 -0
  287. /data/app/javascript/{blacklight → blacklight-frontend}/debounce.js +0 -0
  288. /data/app/javascript/{blacklight → blacklight-frontend}/search_context.js +0 -0
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module Facets
5
+ class ItemComponent < Blacklight::Component
6
+ attr_reader :label, :href, :hits
7
+
8
+ with_collection_parameter :facet_item
9
+
10
+ def initialize(facet_item:, wrapping_element: 'li', suppress_link: false)
11
+ @facet_item = facet_item
12
+ @label = facet_item.label
13
+ @hits = facet_item.hits
14
+ @href = facet_item.href
15
+ @selected = facet_item.selected?
16
+ @wrapping_element = wrapping_element
17
+ @suppress_link = suppress_link
18
+ end
19
+
20
+ def call
21
+ # if the downstream app has overridden the helper methods we'd usually call,
22
+ # use the helpers to preserve compatibility
23
+ content = if @selected
24
+ render_selected_facet_value
25
+ else
26
+ render_facet_value
27
+ end
28
+
29
+ return '' if content.blank?
30
+ return content unless @wrapping_element
31
+
32
+ content_tag @wrapping_element, content
33
+ end
34
+
35
+ ##
36
+ # Standard display of a facet value in a list. Used in both _facets sidebar
37
+ # partial and catalog/facet expanded list. Will output facet value name as
38
+ # a link to add that to your restrictions, with count in parens.
39
+ #
40
+ # @return [String]
41
+ # @private
42
+ def render_facet_value
43
+ tag.span(class: "facet-label") do
44
+ link_to_unless(@suppress_link, label, href, class: "facet-select", rel: "nofollow")
45
+ end + render_facet_count
46
+ end
47
+
48
+ ##
49
+ # Standard display of a SELECTED facet value (e.g. without a link and with a remove button)
50
+ # @see #render_facet_value
51
+ #
52
+ # @private
53
+ def render_selected_facet_value
54
+ concat render(Blacklight::Facets::SelectedValueComponent.new(label: label, href: href))
55
+ concat render_facet_count(classes: ["selected"])
56
+ end
57
+
58
+ ##
59
+ # Renders a count value for facet limits. Can be over-ridden locally
60
+ # to change style. And can be called by plugins to get consistent display.
61
+ #
62
+ # @param [Hash] options
63
+ # @option options [Array<String>] an array of classes to add to count span.
64
+ # @return [String]
65
+ # @private
66
+ def render_facet_count(options = {})
67
+ classes = (options[:classes] || []) << "facet-count"
68
+
69
+ render Blacklight::Facets::CountComponent.new(hits: hits, classes: classes)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,11 @@
1
+ <%= render(@layout.new(facet_field: @facet_field)) do |component| %>
2
+ <% component.with_label do %>
3
+ <%= @facet_field.label %>
4
+ <% end %>
5
+ <% component.with_body do %>
6
+ <%= render(Blacklight::Facets::InclusiveConstraintComponent.new(facet_field: @facet_field)) %>
7
+ <ul class="facet-values list-unstyled">
8
+ <%= render facet_items %>
9
+ </ul>
10
+ <% end %>
11
+ <% end %>
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module Facets
5
+ class ListComponent < Blacklight::Component
6
+ def initialize(facet_field:, layout: nil)
7
+ @facet_field = facet_field
8
+ @layout = layout == false ? Blacklight::Facets::NoLayoutComponent : Blacklight::Facets::FieldComponent
9
+ end
10
+
11
+ def facet_items(wrapping_element: :li, **item_args)
12
+ facet_item_component_class.with_collection(facet_item_presenters, wrapping_element: wrapping_element, **item_args)
13
+ end
14
+
15
+ def facet_item_presenters
16
+ @facet_field.paginator.items.map do |item|
17
+ facet_item_presenter(item)
18
+ end
19
+ end
20
+
21
+ def render?
22
+ @facet_field.paginator&.items&.any?
23
+ end
24
+
25
+ def facet_item_presenter(facet_item)
26
+ facet_config.item_presenter.new(facet_item, facet_config, helpers, @facet_field.key)
27
+ end
28
+
29
+ def facet_item_component_class
30
+ facet_config.item_component
31
+ end
32
+
33
+ def facet_config
34
+ @facet_field.facet_field
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module Facets
5
+ class NoLayoutComponent < Blacklight::Component
6
+ renders_one :label
7
+ renders_one :body
8
+
9
+ def initialize(**); end
10
+
11
+ def call
12
+ body.to_s
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module Facets
5
+ # Standard display of a selected facet value (e.g. without a link and with a remove button)
6
+ class SelectedValueComponent < Blacklight::Component
7
+ def initialize(label:, href:)
8
+ @label = label
9
+ @href = href
10
+ super
11
+ end
12
+
13
+ attr_reader :label, :href
14
+
15
+ def call
16
+ tag.span(class: "facet-label") do
17
+ tag.span(label, class: "selected") + remove_link
18
+ end
19
+ end
20
+
21
+ def remove_link
22
+ link_to(href, class: "remove ps-2", rel: "nofollow") do
23
+ render(Blacklight::Icons::RemoveComponent.new(aria_hidden: true)) +
24
+ tag.span(t(:'blacklight.search.facets.selected.remove'), class: 'visually-hidden')
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ <label for="facet_suggest_<%= key %>">
2
+ <%= I18n.t('blacklight.search.facets.suggest.label', field_label: label) %>
3
+ </label>
4
+ <%= text_field_tag "facet_suggest_#{key}",
5
+ nil,
6
+ class: "facet-suggest form-control mb-3",
7
+ data: {
8
+ facet_field: key,
9
+ facet_search_context: helpers.search_facet_path(id: key)
10
+ },
11
+ placeholder: I18n.t('blacklight.search.form.search.placeholder')
12
+ %>
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module Facets
5
+ class SuggestComponent < Blacklight::Component
6
+ def initialize(presenter:)
7
+ @presenter = presenter
8
+ end
9
+
10
+ private
11
+
12
+ attr_accessor :presenter
13
+
14
+ delegate :suggest, :key, :label, to: :presenter
15
+
16
+ def render?
17
+ # Draw if suggest is true or not present
18
+ suggest != false
19
+ end
20
+ end
21
+ end
22
+ end
@@ -4,8 +4,8 @@ module Blacklight
4
4
  class MetadataFieldPlainTextLayoutComponent < Blacklight::MetadataFieldLayoutComponent
5
5
  with_collection_parameter :field
6
6
 
7
- def initialize(field:, **kwargs)
8
- super(field: field, **kwargs, value_tag: nil)
7
+ def initialize(field:, **)
8
+ super(field: field, **, value_tag: nil)
9
9
  end
10
10
 
11
11
  # rubocop:disable Rails/OutputSafety
@@ -1,27 +1,12 @@
1
1
  <% # main container for facets/limits menu -%>
2
2
  <%= content_tag :div, id: @id, class: 'facets sidenav facets-toggleable-md' do %>
3
3
  <div class="facets-header">
4
- <%= content_tag :h2, @title, class: 'facets-heading' if @title %>
4
+ <%= content_tag :h2, @title, class: 'facets-heading h4' if @title %>
5
5
 
6
- <%= content_tag :button,
7
- class: 'btn btn-outline-secondary facet-toggle-button d-block d-lg-none',
8
- type: 'button',
9
- data: {
10
- toggle: 'collapse',
11
- target: "##{@panel_id}",
12
- 'bs-toggle': 'collapse',
13
- 'bs-target': "##{@panel_id}"
14
- },
15
- aria: {
16
- controls: @panel_id,
17
- expanded: 'false',
18
- } do %>
19
- <span data-show-label><%= t('blacklight.search.facets.group.open') %></span>
20
- <span data-hide-label><%= t('blacklight.search.facets.group.close') %></span>
21
- <% end %>
6
+ <%= collapse_toggle_button(@panel_id) %>
22
7
  </div>
23
8
 
24
- <div id="<%= @panel_id %>" class="facets-collapse collapse">
9
+ <div id="<%= @panel_id %>" class="<%= body_classes %>">
25
10
  <%= body %>
26
11
  </div>
27
12
  <% end %>
@@ -6,41 +6,29 @@ module Blacklight
6
6
  class FacetGroupComponent < Blacklight::Component
7
7
  renders_one :body
8
8
 
9
- # @param [Blacklight::Response] response
10
- # @param [Array<Blacklight::Configuration::FacetField>] fields facet fields to render
11
- # @param [String] title the title of the facet group section
12
9
  # @param [String] id a unique identifier for the group
13
- def initialize(id:, title: nil, fields: [], response: nil)
10
+ # @param [String] title the title of the facet group section
11
+ def initialize(id:, title: nil, body_classes: 'facets-collapse d-lg-block collapse accordion')
14
12
  @groupname = id
15
13
  @id = id ? "facets-#{id}" : 'facets'
16
14
  @title = title || I18n.t("blacklight.search.#{@id}.title")
17
15
  @panel_id = id ? "facet-panel-#{id}-collapse" : 'facet-panel-collapse'
18
-
19
- # deprecated variables
20
- @fields = fields
21
- @response = response
16
+ @body_classes = body_classes
22
17
  end
23
18
 
24
- # Provide fallback behavior for rendering this object without a body slot
25
- def before_render
26
- set_slot(:body, nil) { default_body } unless body?
27
- end
19
+ attr_accessor :body_classes
28
20
 
29
- def render?
30
- body.present?
21
+ def collapse_toggle_button(panel_id)
22
+ render button_component.new(panel_id: panel_id)
31
23
  end
32
24
 
33
- private
34
-
35
- # @deprecated
36
- def default_body
37
- Blacklight.deprecation.warn('Rendering the Blacklight::FacetGroupComponent without a body slot is deprecated.')
38
- render(Blacklight::FacetComponent.with_collection(@fields, response: @response))
25
+ def button_component
26
+ Blacklight::Response::FacetToggleButtonComponent
39
27
  end
40
28
 
41
- # @deprecated
42
- def blacklight_config
43
- helpers.blacklight_config
29
+ def render?
30
+ # debugger
31
+ body.present?
44
32
  end
45
33
  end
46
34
  end
@@ -0,0 +1,16 @@
1
+ <%= content_tag :button,
2
+ class: @classes,
3
+ type: 'button',
4
+ data: {
5
+ toggle: 'collapse',
6
+ target: "##{@panel_id}",
7
+ 'bs-toggle': 'collapse',
8
+ 'bs-target': "##{@panel_id}"
9
+ },
10
+ aria: {
11
+ controls: @panel_id,
12
+ expanded: 'false',
13
+ } do %>
14
+ <span data-show-label><%= t('blacklight.search.facets.group.open') %></span>
15
+ <span data-hide-label><%= t('blacklight.search.facets.group.close') %></span>
16
+ <% end %>
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module Response
5
+ # Render the button that shows or collapses the facets on a narrow viewport
6
+ class FacetToggleButtonComponent < Blacklight::Component
7
+ # @param [String] panel_id
8
+ def initialize(panel_id:, classes: 'btn btn-outline-secondary facet-toggle-button d-block d-lg-none')
9
+ @panel_id = panel_id
10
+ @classes = classes
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
- <%= tag.nav class: 'paginate-section', **html_attr do %>
1
+ <%= tag.nav class: @classes, **html_attr do %>
2
2
  <%= pagination %>
3
3
  <% end %>
@@ -6,9 +6,10 @@ module Blacklight
6
6
  class PaginationComponent < Blacklight::Component
7
7
  # @param [Blacklight::Response] response
8
8
  # @param [Hash] html html options for the pagination container
9
- def initialize(response:, html: {}, **pagination_args)
9
+ def initialize(response:, html: {}, classes: 'paginate-section', **pagination_args)
10
10
  @response = response
11
11
  @html = html
12
+ @classes = classes
12
13
  @pagination_args = pagination_args
13
14
  end
14
15
 
@@ -22,6 +22,7 @@ module Blacklight
22
22
  param: @param,
23
23
  choices: @choices,
24
24
  id: @id,
25
+ classes: @classes,
25
26
  search_state: @search_state,
26
27
  selected: @selected
27
28
  ))
@@ -1,4 +1,4 @@
1
1
  <%= link_to url, title: label, aria: aria_attributes, class: "#{Array(@classes).join(' ')} view-type-#{ @key.to_s.parameterize } #{"active" if selected?}" do %>
2
2
  <%= icon %>
3
- <span class="caption"><%= label %></span>
3
+ <span class="caption visually-hidden"><%= label %></span>
4
4
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <div class="view-type">
2
- <span class="sr-only visually-hidden"><%= t('blacklight.search.view_title') %></span>
2
+ <span class="visually-hidden"><%= t('blacklight.search.view_title') %></span>
3
3
  <div class="view-type-group btn-group">
4
4
  <% views.each do |view| %>
5
5
  <%= view %>
@@ -1,2 +1,2 @@
1
- <span class="sr-only visually-hidden"><%= t('blacklight.search.per_page.title') %></span>
1
+ <span class="visually-hidden"><%= t('blacklight.search.per_page.title') %></span>
2
2
  <%= dropdown %>
@@ -23,6 +23,7 @@ module Blacklight
23
23
  param: :per_page,
24
24
  choices: per_page_options_for_select,
25
25
  id: 'per_page-dropdown',
26
+ classes: ['mx-1'],
26
27
  search_state: @search_state,
27
28
  selected: current_per_page,
28
29
  interpolation: :count
@@ -1,7 +1,7 @@
1
1
  <search>
2
2
  <% facet_group_names.each do |groupname| %>
3
3
  <% fields = facet_fields_in_group(groupname) %>
4
- <%= render group_component_class.new(id: groupname, fields: fields, response: response) do |component| %>
4
+ <%= render group_component_class.new(id: groupname) do |component| %>
5
5
  <% component.with_body do %>
6
6
  <%= render Blacklight::FacetComponent.with_collection(fields, response: response) %>
7
7
  <% end %>
@@ -6,7 +6,7 @@ module Blacklight
6
6
  def initialize(blacklight_config:, response:, view_config:)
7
7
  @blacklight_config = blacklight_config
8
8
  @response = response
9
- @group_component_class = view_config.facet_group_component || Blacklight::Response::FacetGroupComponent
9
+ @group_component_class = view_config.facet_group_component
10
10
  end
11
11
 
12
12
  attr_reader :group_component_class, :response
@@ -2,7 +2,7 @@
2
2
  <%= form_with url: @url, local: true, method: @method, class: @classes.join(' '), scope: @prefix, role: 'search', **@form_options do |f| %>
3
3
  <%= render Blacklight::HiddenSearchStateComponent.new(params: @params) %>
4
4
  <% if search_fields.length > 1 %>
5
- <%= f.label :search_field, scoped_t('search_field.label'), class: 'sr-only visually-hidden' %>
5
+ <%= f.label :search_field, scoped_t('search_field.label'), class: 'visually-hidden' %>
6
6
  <% end %>
7
7
  <% before_input_groups.each do |input_group| %>
8
8
  <%= input_group %>
@@ -20,9 +20,9 @@
20
20
  <%= f.hidden_field :search_field, value: search_fields.first.last %>
21
21
  <% end %>
22
22
 
23
- <%= f.label @query_param, scoped_t('search.label'), class: 'sr-only visually-hidden' %>
23
+ <%= f.label @query_param, scoped_t('search.label'), class: 'visually-hidden' %>
24
24
  <% if autocomplete_path.present? %>
25
- <auto-complete src="<%= autocomplete_path %>" for="autocomplete-popup" class="search-autocomplete-wrapper <%= rounded_border_class %>">
25
+ <auto-complete src="<%= autocomplete_path %>" for="autocomplete-popup" class="search-autocomplete-wrapper form-control <%= rounded_border_class %>">
26
26
  <%= f.search_field @query_param, value: @q, placeholder: scoped_t('search.placeholder'), class: "search-q q form-control #{rounded_border_class}", autofocus: @autofocus, aria: { label: scoped_t('search.label'), autocomplete: 'list', controls: 'autocomplete-popup' } %>
27
27
  <ul id="autocomplete-popup" class="dropdown-menu" role="listbox" aria-label="<%= scoped_t('search.label') %>" hidden></ul>
28
28
  </auto-complete>
@@ -11,7 +11,7 @@ module Blacklight
11
11
  def initialize(
12
12
  url:, params:,
13
13
  advanced_search_url: nil,
14
- classes: ['search-query-form'], prefix: nil,
14
+ classes: %w[search-query-form col-md-12 col-lg-8], prefix: nil,
15
15
  method: 'GET', q: nil, query_param: :q,
16
16
  search_field: nil, autocomplete_path: nil,
17
17
  autofocus: nil, i18n: { scope: 'blacklight.search.form' },
@@ -63,7 +63,7 @@ module Blacklight
63
63
  def rounded_border_class
64
64
  return 'rounded-0' if search_fields.length > 1
65
65
 
66
- 'rounded-left rounded-start'
66
+ 'rounded-start'
67
67
  end
68
68
 
69
69
  private
@@ -8,8 +8,8 @@ module Blacklight
8
8
  end
9
9
 
10
10
  def call
11
- tag.button(class: 'btn btn-primary search-btn', type: 'submit', id: @id) do
12
- tag.span(@text, class: "visually-hidden-sm me-sm-1 submit-search-text") +
11
+ tag.button(class: 'btn btn-primary search-btn', type: 'submit', id: @id, aria: { label: @text }) do
12
+ tag.span(@text, class: "d-none d-md-inline me-sm-1 submit-search-text", aria: { hidden: true }) +
13
13
  render(Blacklight::Icons::SearchComponent.new)
14
14
  end
15
15
  end
@@ -1,4 +1,4 @@
1
- <div id="appliedParams" class="clearfix constraints-container">
2
- <%= render 'start_over' %>
1
+ <div id="appliedParams" class="clearfix constraints-container mb-2">
2
+ <%= start_over %>
3
3
  <%= link_back_to_catalog class: 'btn btn-outline-secondary' %>
4
4
  </div>
@@ -2,12 +2,21 @@
2
2
 
3
3
  module Blacklight
4
4
  module SearchContext
5
+ # This is displayed on the show page when the user has a search session.
5
6
  class ServerAppliedParamsComponent < Blacklight::Component
6
7
  delegate :current_search_session, :link_back_to_catalog, to: :helpers
7
8
 
8
9
  def render?
9
10
  current_search_session
10
11
  end
12
+
13
+ def start_over
14
+ render start_over_component.new
15
+ end
16
+
17
+ def start_over_component
18
+ Blacklight::StartOverButtonComponent
19
+ end
11
20
  end
12
21
  end
13
22
  end
@@ -1,4 +1,4 @@
1
- <nav id="skip-link" class="visually-hidden-focusable sr-only sr-only-focusable" aria-label="<%= t('blacklight.skip_links.label') %>">
1
+ <nav id="skip-link" class="visually-hidden-focusable" aria-label="<%= t('blacklight.skip_links.label') %>">
2
2
  <div class="container-xl">
3
3
  <%= link_to_main %>
4
4
  <%= link_to_search %>
@@ -20,7 +20,8 @@ module Blacklight
20
20
  delegate :skip_link_item_component, to: :blacklight_config
21
21
 
22
22
  def link_classes
23
- 'd-inline-flex p-2 m-1'
23
+ Blacklight.deprecation.warn("Use SkipLinkItemComponent instead")
24
+ 'visually-hidden-focusable rounded-bottom py-2 px-3'
24
25
  end
25
26
  end
26
27
  end
@@ -1,7 +1,7 @@
1
- <nav class="navbar navbar-expand-md navbar-dark bg-dark topbar" aria-label="<%= aria_label %>">
1
+ <nav class="navbar navbar-expand-md bg-dark topbar" aria-label="<%= aria_label %>">
2
2
  <div class="<%= container_classes %>">
3
3
  <%= logo_link %>
4
- <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-bs-toggle="collapse" data-target="#user-util-collapse" data-bs-target="#user-util-collapse" aria-controls="user-util-collapse" aria-expanded="false" aria-label="Toggle navigation">
4
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-bs-toggle="collapse" data-target="#user-util-collapse" data-bs-target="#user-util-collapse" aria-controls="user-util-collapse" aria-expanded="false" aria-label="Toggle navigation">
5
5
  <span class="navbar-toggler-icon"></span>
6
6
  </button>
7
7
 
@@ -36,8 +36,8 @@ module Blacklight::Bookmarks
36
36
 
37
37
  # Blacklight uses #search_action_url to figure out the right URL for
38
38
  # the global search box
39
- def search_action_url *args
40
- search_catalog_url(*args)
39
+ def search_action_url(*)
40
+ search_catalog_url(*)
41
41
  end
42
42
 
43
43
  # @return [Hash] a hash of context information to pass through to the search service
@@ -110,7 +110,7 @@ module Blacklight::Bookmarks
110
110
 
111
111
  success = @bookmarks.all? do |bookmark|
112
112
  bookmark = current_or_guest_user.bookmarks.find_by(bookmark)
113
- bookmark && bookmark.delete && bookmark.destroyed?
113
+ bookmark&.delete && bookmark.destroyed?
114
114
  end
115
115
 
116
116
  if success
@@ -9,13 +9,13 @@ module Blacklight::Catalog
9
9
  include Blacklight::Configurable
10
10
  include Blacklight::SearchContext
11
11
  include Blacklight::Searchable
12
+ include Blacklight::Facetable
12
13
 
13
14
  # The following code is executed when someone includes blacklight::catalog in their
14
15
  # own controller.
15
16
  included do
16
17
  if respond_to? :helper_method
17
18
  helper_method :sms_mappings, :has_search_parameters?
18
- helper_method :search_facet_path
19
19
  end
20
20
 
21
21
  record_search_parameters
@@ -80,16 +80,19 @@ module Blacklight::Catalog
80
80
 
81
81
  # displays values and pagination links for a single facet field
82
82
  def facet
83
+ # @facet is a Blacklight::Configuration::FacetField
83
84
  @facet = blacklight_config.facet_fields[params[:id]]
84
85
  raise ActionController::RoutingError, 'Not Found' unless @facet
85
86
 
86
87
  @response = if params[:query_fragment].present?
87
- search_service.facet_suggest_response(@facet.key, params[:query_fragment])
88
+ facet_search_service.facet_suggest_response(@facet.key, params[:query_fragment])
88
89
  else
89
- search_service.facet_field_response(@facet.key)
90
+ facet_search_service.facet_field_response(@facet.key)
90
91
  end
92
+
91
93
  @display_facet = @response.aggregations[@facet.field]
92
94
 
95
+ # @presenter is a Blacklight::FacetFieldPresenter
93
96
  @presenter = @facet.presenter.new(@facet, @display_facet, view_context)
94
97
  @pagination = @presenter.paginator
95
98
  respond_to do |format|
@@ -138,15 +141,6 @@ module Blacklight::Catalog
138
141
  params[:search_field].present? || search_state.has_constraints?
139
142
  end
140
143
 
141
- def search_facet_path(options = {})
142
- opts = search_state
143
- .to_h
144
- .merge(action: "facet", only_path: true)
145
- .merge(options)
146
- .except(:page)
147
- url_for opts
148
- end
149
-
150
144
  private
151
145
 
152
146
  #
@@ -235,22 +229,14 @@ module Blacklight::Catalog
235
229
  # Email Action (this will render the appropriate view on GET requests and process the form and send the email on POST requests)
236
230
  def email_action documents
237
231
  mail = RecordMailer.email_record(documents, { to: params[:to], message: params[:message], config: blacklight_config }, url_options)
238
- if mail.respond_to? :deliver_now
239
- mail.deliver_now
240
- else
241
- mail.deliver
242
- end
232
+ mail.deliver_now
243
233
  end
244
234
 
245
235
  # SMS action (this will render the appropriate view on GET requests and process the form and send the email on POST requests)
246
236
  def sms_action documents
247
237
  to = "#{params[:to].gsub(/[^\d]/, '')}@#{params[:carrier]}"
248
238
  mail = RecordMailer.sms_record(documents, { to: to, config: blacklight_config }, url_options)
249
- if mail.respond_to? :deliver_now
250
- mail.deliver_now
251
- else
252
- mail.deliver
253
- end
239
+ mail.deliver_now
254
240
  end
255
241
 
256
242
  def validate_sms_params
@@ -292,7 +278,7 @@ module Blacklight::Catalog
292
278
  def blacklight_advanced_search_form_search_service
293
279
  form_search_state = search_state_class.new(blacklight_advanced_search_form_params, blacklight_config, self)
294
280
 
295
- search_service_class.new(config: blacklight_config, search_state: form_search_state, user_params: form_search_state.to_h, **search_service_context)
281
+ search_service_class.new(config: blacklight_config, search_state: form_search_state, **search_service_context)
296
282
  end
297
283
 
298
284
  def blacklight_advanced_search_form_params
@@ -130,7 +130,7 @@ module Blacklight::Controller
130
130
  # send the user home if the access was previously denied by the same
131
131
  # request to avoid sending the user back to the login page
132
132
  # (e.g. protected page -> logout -> returned to protected page -> home)
133
- redirect_to(root_url) && flash.discard && return if request.referer && request.referer.ends_with?(request.fullpath)
133
+ redirect_to(root_url) && flash.discard && return if request.referer&.ends_with?(request.fullpath)
134
134
 
135
135
  redirect_to(root_url) && return unless has_user_authentication_provider?
136
136