blacklight 8.2.2 → 8.4.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 (225) hide show
  1. checksums.yaml +4 -4
  2. data/.env +1 -1
  3. data/.github/workflows/ruby.yml +60 -62
  4. data/.rubocop.yml +229 -21
  5. data/.rubocop_todo.yml +22 -55
  6. data/Gemfile +2 -10
  7. data/README.md +2 -2
  8. data/VERSION +1 -1
  9. data/app/assets/javascripts/blacklight/blacklight.esm.js +5 -1
  10. data/app/assets/javascripts/blacklight/blacklight.esm.js.map +1 -1
  11. data/app/assets/javascripts/blacklight/blacklight.js +5 -1
  12. data/app/assets/javascripts/blacklight/blacklight.js.map +1 -1
  13. data/app/assets/stylesheets/blacklight/_balanced_list.scss +1 -1
  14. data/app/assets/stylesheets/blacklight/_bookmark.scss +30 -0
  15. data/app/assets/stylesheets/blacklight/_bootstrap_overrides.scss +0 -4
  16. data/app/assets/stylesheets/blacklight/_constraints.scss +15 -9
  17. data/app/assets/stylesheets/blacklight/_controls.scss +0 -1
  18. data/app/assets/stylesheets/blacklight/_facets.scss +33 -37
  19. data/app/assets/stylesheets/blacklight/_header.scss +2 -35
  20. data/app/assets/stylesheets/blacklight/_icons.scss +3 -2
  21. data/app/assets/stylesheets/blacklight/_layout.scss +3 -0
  22. data/app/assets/stylesheets/blacklight/_mixins.scss +6 -21
  23. data/app/assets/stylesheets/blacklight/_search_form.scss +3 -8
  24. data/app/assets/stylesheets/blacklight/_search_history.scss +5 -5
  25. data/app/assets/stylesheets/blacklight/_search_results.scss +5 -2
  26. data/app/assets/stylesheets/blacklight/blacklight_defaults.scss +16 -10
  27. data/app/components/blacklight/advanced_search_form_component.html.erb +1 -1
  28. data/app/components/blacklight/advanced_search_form_component.rb +6 -0
  29. data/app/components/blacklight/constraint_layout_component.html.erb +2 -9
  30. data/app/components/blacklight/constraint_layout_component.rb +8 -0
  31. data/app/components/blacklight/constraints_component.rb +3 -3
  32. data/app/components/blacklight/document/action_component.rb +2 -1
  33. data/app/components/blacklight/document/bookmark_component.html.erb +2 -1
  34. data/app/components/blacklight/document/bookmark_component.rb +6 -0
  35. data/app/components/blacklight/document/page_header_component.html.erb +7 -0
  36. data/app/components/blacklight/document/page_header_component.rb +85 -0
  37. data/app/components/blacklight/document_component.rb +1 -1
  38. data/app/components/blacklight/facet_component.rb +1 -1
  39. data/app/components/blacklight/facet_field_checkboxes_component.html.erb +1 -1
  40. data/app/components/blacklight/facet_field_checkboxes_component.rb +1 -1
  41. data/app/components/blacklight/facet_field_inclusive_constraint_component.html.erb +1 -1
  42. data/app/components/blacklight/facet_field_list_component.html.erb +1 -1
  43. data/app/components/blacklight/facet_item_component.rb +1 -1
  44. data/app/components/blacklight/facet_item_pivot_component.rb +2 -2
  45. data/app/components/blacklight/icons/bookmark_icon_component.rb +17 -0
  46. data/app/components/blacklight/icons/icon_component.rb +9 -4
  47. data/app/components/blacklight/icons/remove_component.rb +16 -0
  48. data/app/components/blacklight/metadata_field_component.html.erb +1 -1
  49. data/app/components/blacklight/metadata_field_component.rb +5 -0
  50. data/app/components/blacklight/response/facet_group_component.rb +1 -1
  51. data/app/components/blacklight/response/pagination_component.html.erb +1 -1
  52. data/app/components/blacklight/response/sort_component.html.erb +1 -6
  53. data/app/components/blacklight/response/sort_component.rb +15 -0
  54. data/app/components/blacklight/search/per_page_component.html.erb +2 -0
  55. data/app/components/blacklight/search/per_page_component.rb +50 -0
  56. data/app/components/blacklight/search_bar_component.html.erb +1 -1
  57. data/app/components/blacklight/search_context/server_item_pagination_component.html.erb +4 -7
  58. data/app/components/blacklight/skip_link_component.html.erb +7 -0
  59. data/app/components/blacklight/skip_link_component.rb +17 -0
  60. data/app/components/blacklight/system/dropdown_button_component.rb +18 -0
  61. data/app/components/blacklight/system/dropdown_component.rb +4 -7
  62. data/app/components/blacklight/system/flash_message_component.html.erb +1 -1
  63. data/app/components/blacklight/top_navbar_component.html.erb +2 -2
  64. data/app/components/blacklight/top_navbar_component.rb +4 -0
  65. data/app/helpers/blacklight/catalog_helper_behavior.rb +3 -5
  66. data/app/helpers/blacklight/component_helper_behavior.rb +4 -4
  67. data/app/helpers/blacklight/configuration_helper_behavior.rb +2 -0
  68. data/app/helpers/blacklight/layout_helper_behavior.rb +3 -3
  69. data/app/javascript/blacklight/checkbox_submit.js +5 -1
  70. data/app/models/concerns/blacklight/document/semantic_fields.rb +1 -1
  71. data/app/presenters/blacklight/facet_checkbox_item_presenter.rb +11 -0
  72. data/app/presenters/blacklight/facet_field_presenter.rb +9 -1
  73. data/app/services/blacklight/search_service.rb +9 -1
  74. data/app/views/catalog/_per_page_widget.html.erb +1 -10
  75. data/app/views/catalog/_search_results.html.erb +1 -1
  76. data/app/views/catalog/_show_main_content.html.erb +1 -1
  77. data/app/views/catalog/show.html.erb +0 -2
  78. data/app/views/catalog/suggest.html.erb +1 -1
  79. data/app/views/kaminari/blacklight/_page.html.erb +14 -8
  80. data/app/views/layouts/blacklight/base.html.erb +3 -4
  81. data/app/views/shared/_flash_messages.html.erb +1 -1
  82. data/blacklight.gemspec +4 -0
  83. data/{docker-compose.yml → compose.yaml} +1 -1
  84. data/config/locales/blacklight.ar.yml +3 -0
  85. data/config/locales/blacklight.de.yml +3 -0
  86. data/config/locales/blacklight.en.yml +216 -229
  87. data/config/locales/blacklight.es.yml +3 -0
  88. data/config/locales/blacklight.fr.yml +3 -0
  89. data/config/locales/blacklight.hu.yml +3 -0
  90. data/config/locales/blacklight.it.yml +3 -0
  91. data/config/locales/blacklight.nl.yml +3 -0
  92. data/config/locales/blacklight.pt-BR.yml +3 -0
  93. data/config/locales/blacklight.sq.yml +3 -0
  94. data/config/locales/blacklight.zh.yml +3 -0
  95. data/lib/blacklight/abstract_repository.rb +6 -0
  96. data/lib/blacklight/configuration.rb +33 -19
  97. data/lib/blacklight/nested_open_struct_with_hash_access.rb +2 -2
  98. data/lib/blacklight/parameters.rb +1 -1
  99. data/lib/blacklight/solr/repository.rb +11 -4
  100. data/lib/blacklight/solr/request.rb +1 -1
  101. data/lib/blacklight/solr/response/facets.rb +1 -1
  102. data/lib/blacklight/solr/response/params.rb +1 -1
  103. data/lib/blacklight/solr/response.rb +0 -12
  104. data/lib/blacklight/solr/search_builder_behavior.rb +2 -2
  105. data/lib/blacklight/solr.rb +0 -6
  106. data/lib/blacklight.rb +4 -14
  107. data/lib/generators/blacklight/assets/propshaft_generator.rb +2 -2
  108. data/lib/generators/blacklight/models_generator.rb +1 -1
  109. data/package.json +1 -1
  110. data/spec/components/blacklight/advanced_search_form_component_spec.rb +2 -2
  111. data/spec/components/blacklight/constraint_layout_component_spec.rb +11 -11
  112. data/spec/components/blacklight/constraints_component_spec.rb +9 -9
  113. data/spec/components/blacklight/document/action_component_spec.rb +1 -1
  114. data/spec/components/blacklight/document/group_component_spec.rb +3 -3
  115. data/spec/components/blacklight/document/page_header_component_spec.rb +92 -0
  116. data/spec/components/blacklight/document/sidebar_component_spec.rb +3 -4
  117. data/spec/components/blacklight/document_component_spec.rb +41 -25
  118. data/spec/components/blacklight/facet_component_spec.rb +2 -2
  119. data/spec/components/blacklight/facet_field_checkboxes_component_spec.rb +5 -5
  120. data/spec/components/blacklight/facet_field_list_component_spec.rb +13 -13
  121. data/spec/components/blacklight/facet_item_component_spec.rb +5 -5
  122. data/spec/components/blacklight/facet_item_pivot_component_spec.rb +6 -6
  123. data/spec/components/blacklight/header_component_spec.rb +1 -2
  124. data/spec/components/blacklight/hidden_search_state_component_spec.rb +6 -6
  125. data/spec/components/blacklight/icons/icon_component_spec.rb +42 -0
  126. data/spec/components/blacklight/metadata_field_component_spec.rb +3 -3
  127. data/spec/components/blacklight/response/pagination_component_spec.rb +4 -4
  128. data/spec/components/blacklight/search_context/server_applied_params_component_spec.rb +1 -1
  129. data/spec/components/blacklight/search_context/server_item_pagination_component_spec.rb +2 -4
  130. data/spec/components/blacklight/system/flash_message_component_spec.rb +5 -5
  131. data/spec/controllers/blacklight/catalog_spec.rb +2 -2
  132. data/spec/controllers/blacklight/{catalog/component_configuration_spec.rb → configurable_spec.rb} +1 -1
  133. data/spec/controllers/bookmarks_controller_spec.rb +10 -10
  134. data/spec/controllers/catalog_controller_spec.rb +29 -31
  135. data/spec/features/advanced_search_spec.rb +30 -16
  136. data/spec/features/alternate_controller_spec.rb +9 -9
  137. data/spec/features/axe_spec.rb +4 -4
  138. data/spec/features/bookmarks_spec.rb +34 -19
  139. data/spec/features/citation_spec.rb +1 -1
  140. data/spec/features/did_you_mean_spec.rb +23 -23
  141. data/spec/features/facet_missing_spec.rb +9 -9
  142. data/spec/features/facets_spec.rb +21 -20
  143. data/spec/features/modal_spec.rb +4 -4
  144. data/spec/features/record_view_spec.rb +2 -2
  145. data/spec/features/search_context_spec.rb +6 -6
  146. data/spec/features/search_crawler_spec.rb +5 -5
  147. data/spec/features/search_filters_spec.rb +65 -65
  148. data/spec/features/search_history_spec.rb +12 -12
  149. data/spec/features/search_pagination_spec.rb +10 -10
  150. data/spec/features/search_results_spec.rb +1 -1
  151. data/spec/features/search_sort_spec.rb +4 -4
  152. data/spec/features/search_spec.rb +25 -25
  153. data/spec/features/sitelinks_search_box_spec.rb +2 -2
  154. data/spec/features/sms_spec.rb +1 -1
  155. data/spec/helpers/blacklight/facets_helper_behavior_spec.rb +2 -2
  156. data/spec/helpers/blacklight/layout_helper_behavior_spec.rb +20 -3
  157. data/spec/helpers/blacklight/render_partials_helper_behavior_spec.rb +2 -1
  158. data/spec/helpers/blacklight/url_helper_behavior_spec.rb +7 -8
  159. data/spec/helpers/blacklight_helper_spec.rb +13 -15
  160. data/spec/helpers/catalog_helper_spec.rb +3 -6
  161. data/spec/i18n_spec.rb +2 -1
  162. data/spec/lib/blacklight/nested_open_struct_with_hash_access_spec.rb +1 -1
  163. data/spec/lib/blacklight/open_struct_with_hash_access_spec.rb +1 -1
  164. data/spec/lib/blacklight/search_state_spec.rb +4 -4
  165. data/spec/lib/tasks/blacklight_task_spec.rb +2 -1
  166. data/spec/models/blacklight/configurable_spec.rb +1 -1
  167. data/spec/models/blacklight/configuration/context_spec.rb +1 -1
  168. data/spec/models/blacklight/configuration_spec.rb +14 -14
  169. data/spec/models/blacklight/document/active_model_shim_spec.rb +1 -1
  170. data/spec/models/blacklight/document/cache_key_spec.rb +1 -1
  171. data/spec/models/blacklight/document_spec.rb +1 -1
  172. data/spec/models/blacklight/facet_paginator_spec.rb +14 -14
  173. data/spec/models/blacklight/icon_spec.rb +1 -1
  174. data/spec/models/blacklight/search_builder_spec.rb +1 -1
  175. data/spec/models/blacklight/solr/document_spec.rb +3 -3
  176. data/spec/models/blacklight/solr/facet_paginator_spec.rb +1 -1
  177. data/spec/models/blacklight/solr/repository_spec.rb +33 -15
  178. data/spec/models/blacklight/solr/request_spec.rb +1 -1
  179. data/spec/models/blacklight/solr/response/facets_spec.rb +3 -3
  180. data/spec/models/blacklight/solr/response/group_response_spec.rb +1 -1
  181. data/spec/models/blacklight/solr/response/group_spec.rb +2 -2
  182. data/spec/models/blacklight/solr/response_spec.rb +3 -3
  183. data/spec/models/blacklight/solr/{search_builder_spec.rb → search_builder_behavior_spec.rb} +10 -20
  184. data/spec/models/blacklight/suggest/response_spec.rb +1 -1
  185. data/spec/models/blacklight/suggest_search_spec.rb +1 -1
  186. data/spec/models/blacklight/user_spec.rb +1 -1
  187. data/spec/models/bookmark_spec.rb +1 -1
  188. data/spec/models/solr_document_spec.rb +1 -1
  189. data/spec/presenters/blacklight/document_presenter_spec.rb +3 -4
  190. data/spec/presenters/blacklight/facet_checkbox_item_presenter_spec.rb +42 -0
  191. data/spec/presenters/blacklight/facet_field_presenter_spec.rb +14 -0
  192. data/spec/presenters/blacklight/field_presenter_spec.rb +1 -1
  193. data/spec/presenters/blacklight/index_presenter_spec.rb +2 -3
  194. data/spec/presenters/blacklight/json_presenter_spec.rb +1 -1
  195. data/spec/presenters/{pipeline_spec.rb → blacklight/rendering/pipeline_spec.rb} +1 -1
  196. data/spec/presenters/blacklight/show_presenter_spec.rb +5 -6
  197. data/spec/presenters/{thumbnail_presenter_spec.rb → blacklight/thumbnail_presenter_spec.rb} +5 -3
  198. data/spec/requests/load_suggestions_spec.rb +5 -5
  199. data/spec/routing/catalog_routing_spec.rb +1 -1
  200. data/spec/services/blacklight/field_retriever_spec.rb +1 -1
  201. data/spec/services/blacklight/search_service_spec.rb +11 -11
  202. data/spec/spec_helper.rb +2 -2
  203. data/spec/support/features/search_helpers.rb +2 -2
  204. data/spec/support/features/session_helpers.rb +3 -3
  205. data/spec/test_app_templates/lib/generators/test_app_generator.rb +3 -3
  206. data/spec/views/catalog/_document.html.erb_spec.rb +1 -4
  207. data/spec/views/catalog/_document_list.html.erb_spec.rb +2 -2
  208. data/spec/views/catalog/_facet_index_navigation.html.erb_spec.rb +5 -6
  209. data/spec/views/catalog/_facet_layout.html.erb_spec.rb +7 -7
  210. data/spec/views/catalog/_paginate_compact.html.erb_spec.rb +4 -4
  211. data/spec/views/catalog/_show_sidebar.erb_spec.rb +1 -4
  212. data/spec/views/catalog/_show_tools.html.erb_spec.rb +1 -2
  213. data/spec/views/catalog/_view_type_group.html.erb_spec.rb +7 -7
  214. data/spec/views/catalog/email_success.html.erb_spec.rb +1 -1
  215. data/spec/views/catalog/facet.html.erb_spec.rb +1 -1
  216. data/spec/views/catalog/facet.json.jbuilder_spec.rb +1 -1
  217. data/spec/views/catalog/index.atom.builder_spec.rb +18 -19
  218. data/spec/views/catalog/index.html.erb_spec.rb +2 -4
  219. data/spec/views/catalog/index.json.jbuilder_spec.rb +5 -8
  220. data/spec/views/catalog/show.html.erb_spec.rb +3 -5
  221. data/spec/views/catalog/show.json.jbuilder_spec.rb +1 -2
  222. data/spec/views/catalog/sms_success.html.erb_spec.rb +1 -1
  223. data/spec/views/shared/_user_util_links.html.erb_spec.rb +2 -3
  224. data/tasks/blacklight.rake +5 -5
  225. metadata +84 -12
@@ -16,7 +16,7 @@
16
16
  <span class="facet-label"><%= presenter.label %></span>
17
17
  <span class="facet-count"><%= t('blacklight.search.facets.count', number: number_with_delimiter(presenter.hits)) %></span>
18
18
  <% end %>
19
- <span>
19
+ </span>
20
20
  </li>
21
21
  <% end -%>
22
22
  </ul>
@@ -17,7 +17,7 @@ module Blacklight
17
17
  return to_enum(:presenters) unless block_given?
18
18
 
19
19
  @facet_field.paginator.items.each do |item|
20
- yield @facet_field.facet_field.item_presenter.new(item, @facet_field.facet_field, helpers, @facet_field.key, @facet_field.search_state)
20
+ yield Blacklight::FacetCheckboxItemPresenter.new(item, @facet_field.facet_field, helpers, @facet_field.key, @facet_field.search_state)
21
21
  end
22
22
  end
23
23
  end
@@ -1,6 +1,6 @@
1
1
  <div class="inclusive_or card card-body bg-light mb-3">
2
2
  <h5><%= t('blacklight.advanced_search.any_of') %></h5>
3
3
  <ul class="list-unstyled facet-values">
4
- <%= helpers.render(Blacklight::FacetItemComponent.with_collection(presenters.to_a)) %>
4
+ <%= render(Blacklight::FacetItemComponent.with_collection(presenters.to_a)) %>
5
5
  </ul>
6
6
  </div>
@@ -3,7 +3,7 @@
3
3
  <%= @facet_field.label %>
4
4
  <% end %>
5
5
  <% component.with_body do %>
6
- <%= helpers.render(Blacklight::FacetFieldInclusiveConstraintComponent.new(facet_field: @facet_field)) %>
6
+ <%= render(Blacklight::FacetFieldInclusiveConstraintComponent.new(facet_field: @facet_field)) %>
7
7
  <ul class="facet-values list-unstyled">
8
8
  <%= render facet_items %>
9
9
  </ul>
@@ -54,7 +54,7 @@ module Blacklight
54
54
  tag.span(label, class: "selected") +
55
55
  # remove link
56
56
  link_to(href, class: "remove", rel: "nofollow") do
57
- tag.span('✖', class: "remove-icon", aria: { hidden: true }) +
57
+ render(Blacklight::Icons::RemoveComponent.new) +
58
58
  tag.span(helpers.t(:'blacklight.search.facets.selected.remove'), class: 'sr-only visually-hidden')
59
59
  end
60
60
  end + render_facet_count(classes: ["selected"])
@@ -52,13 +52,13 @@ module Blacklight
52
52
  private
53
53
 
54
54
  def has_items?
55
- return unless @facet_item.respond_to? :facet_item_presenters
55
+ return false unless @facet_item.respond_to? :facet_item_presenters
56
56
 
57
57
  @facet_item.facet_item_presenters.any?
58
58
  end
59
59
 
60
60
  def expanded?
61
- return unless @collapsing
61
+ return false unless @collapsing
62
62
 
63
63
  @facet_item.shown?
64
64
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module Icons
5
+ class BookmarkIconComponent < Blacklight::Icons::IconComponent
6
+ self.svg = <<~SVG
7
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bookmark-check-fill bookmark-checked" viewBox="0 0 16 16">
8
+ <path fill-rule="evenodd" d="M2 15.5V2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.74.439L8 13.069l-5.26 2.87A.5.5 0 0 1 2 15.5m8.854-9.646a.5.5 0 0 0-.708-.708L7.5 7.793 6.354 6.646a.5.5 0 1 0-.708.708l1.5 1.5a.5.5 0 0 0 .708 0z"/>
9
+ </svg>
10
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bookmark-plus bookmark-unchecked" viewBox="0 0 16 16">
11
+ <path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1z"/>
12
+ <path d="M8 4a.5.5 0 0 1 .5.5V6H10a.5.5 0 0 1 0 1H8.5v1.5a.5.5 0 0 1-1 0V7H6a.5.5 0 0 1 0-1h1.5V4.5A.5.5 0 0 1 8 4"/>
13
+ </svg>
14
+ SVG
15
+ end
16
+ end
17
+ end
@@ -2,15 +2,16 @@
2
2
 
3
3
  module Blacklight
4
4
  module Icons
5
- # This is the list icon for the search button.
5
+ # This is the base class for icon components. You should extend this class for each icon.
6
+ #
6
7
  # You can override the default svg by setting:
7
- # Blacklight::Icons::ListComponent.svg = '<svg>your SVG here</svg>'
8
+ # Blacklight::Icons::MyIconComponent.svg = '<svg>your SVG here</svg>'
8
9
  class IconComponent < ::ViewComponent::Base
9
10
  # rubocop:disable Metrics/ParameterLists
10
11
  def initialize(svg: nil, tag: :span, name: nil, label: nil, aria_hidden: nil, classes: nil, **options)
11
12
  self.svg = svg if svg
12
- @classes = Array(classes) + ['blacklight-icons', "blacklight-icons-#{name}"]
13
13
  @name = name
14
+ @assigned_classes = Array(classes)
14
15
  @tag = tag
15
16
  @options = options.merge(aria: options.fetch(:aria, {}).reverse_merge(label: label, hidden: aria_hidden))
16
17
  end
@@ -18,12 +19,16 @@ module Blacklight
18
19
 
19
20
  def call
20
21
  tag.public_send(@tag, svg&.html_safe, # rubocop:disable Rails/OutputSafety
21
- class: @classes,
22
+ class: classes,
22
23
  **@options)
23
24
  end
24
25
 
25
26
  class_attribute :svg
26
27
 
28
+ def classes
29
+ @classes ||= @assigned_classes + ['blacklight-icons', "blacklight-icons-#{name}"]
30
+ end
31
+
27
32
  def name
28
33
  @name ||= self.class.name.demodulize.underscore.sub('_component', '')
29
34
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module Icons
5
+ # This is the remove (x) icon for the facets and constraints.
6
+ # You can override the default svg by setting:
7
+ # Blacklight::Icons::RemoveComponent.svg = '<svg>your SVG here</svg>'
8
+ class RemoveComponent < Blacklight::Icons::IconComponent
9
+ self.svg = <<~SVG
10
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x fs-4" viewBox="0 0 16 16">
11
+ <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/>
12
+ </svg>
13
+ SVG
14
+ end
15
+ end
16
+ end
@@ -3,6 +3,6 @@
3
3
  <%= label %>
4
4
  <% end %>
5
5
  <% component.with_value do %>
6
- <%= @field.render %>
6
+ <%= render_field %>
7
7
  <% end %>
8
8
  <% end %>
@@ -26,6 +26,11 @@ module Blacklight
26
26
  @field.render_field?
27
27
  end
28
28
 
29
+ # Override this method in a subclass to change the way this value is rendered
30
+ def render_field
31
+ @field.render
32
+ end
33
+
29
34
  ##
30
35
  # Render the index field label for a document
31
36
  #
@@ -35,7 +35,7 @@ module Blacklight
35
35
  # @deprecated
36
36
  def default_body
37
37
  Blacklight.deprecation.warn('Rendering the Blacklight::FacetGroupComponent without a body slot is deprecated.')
38
- helpers.render(Blacklight::FacetComponent.with_collection(@fields, response: @response))
38
+ render(Blacklight::FacetComponent.with_collection(@fields, response: @response))
39
39
  end
40
40
 
41
41
  # @deprecated
@@ -1,3 +1,3 @@
1
- <%= content_tag :section, class: 'paginate-section', **html_attr do %>
1
+ <%= tag.nav class: 'paginate-section', **html_attr do %>
2
2
  <%= pagination %>
3
3
  <% end %>
@@ -1,6 +1 @@
1
- <%= helpers.render(Blacklight::System::DropdownComponent.new(
2
- param: @param,
3
- choices: @choices,
4
- id: @id,
5
- search_state: @search_state,
6
- selected: @selected)) %>
1
+ <%= dropdown %>
@@ -11,6 +11,21 @@ module Blacklight
11
11
  @classes = classes
12
12
  @selected = selected
13
13
  end
14
+
15
+ # You may override this method in a subclass if you want to use a different dropdown component
16
+ def dropdown_class
17
+ helpers.blacklight_config.view_config(:show).dropdown_component
18
+ end
19
+
20
+ def dropdown
21
+ render(dropdown_class.new(
22
+ param: @param,
23
+ choices: @choices,
24
+ id: @id,
25
+ search_state: @search_state,
26
+ selected: @selected
27
+ ))
28
+ end
14
29
  end
15
30
  end
16
31
  end
@@ -0,0 +1,2 @@
1
+ <span class="sr-only visually-hidden"><%= t('blacklight.search.per_page.title') %></span>
2
+ <%= dropdown %>
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module Search
5
+ class PerPageComponent < Blacklight::Component
6
+ def initialize(blacklight_config:, response:, search_state:)
7
+ @blacklight_config = blacklight_config
8
+ @response = response
9
+ @search_state = search_state
10
+ end
11
+
12
+ def render?
13
+ helpers.show_sort_and_per_page?
14
+ end
15
+
16
+ # You may override this method in a subclass if you want to use a different dropdown component
17
+ def dropdown_class
18
+ @blacklight_config.view_config(:show).dropdown_component
19
+ end
20
+
21
+ def dropdown
22
+ render(dropdown_class.new(
23
+ param: :per_page,
24
+ choices: per_page_options_for_select,
25
+ id: 'per_page-dropdown',
26
+ search_state: @search_state,
27
+ selected: current_per_page,
28
+ interpolation: :count
29
+ ))
30
+ end
31
+
32
+ #
33
+ # @return [Integer]
34
+ def current_per_page
35
+ (@response.rows if @response && @response.rows > 0) || # rubocop:disable Style/NumericPredicate
36
+ params.fetch(:per_page, @blacklight_config.default_per_page).to_i
37
+ end
38
+
39
+ ##
40
+ # The available options for results per page, in the style of #options_for_select
41
+ def per_page_options_for_select
42
+ return [] if @blacklight_config.per_page.blank?
43
+
44
+ @blacklight_config.per_page.map do |count|
45
+ [t(:'blacklight.search.per_page.label', count: count).html_safe, count]
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -24,7 +24,7 @@
24
24
  <% if autocomplete_path.present? %>
25
25
  <auto-complete src="<%= autocomplete_path %>" for="autocomplete-popup" class="search-autocomplete-wrapper">
26
26
  <%= f.search_field @query_param, value: @q, placeholder: scoped_t('search.placeholder'), class: "search-q q form-control rounded-#{search_fields.length > 1 ? '0' : 'left'}", autofocus: @autofocus, aria: { label: scoped_t('search.label'), autocomplete: 'list', controls: 'autocomplete-popup' } %>
27
- <ul id="autocomplete-popup" role="listbox" aria-label="<%= scoped_t('search.label') %>" hidden></ul>
27
+ <ul id="autocomplete-popup" class="dropdown-menu" role="listbox" aria-label="<%= scoped_t('search.label') %>" hidden></ul>
28
28
  </auto-complete>
29
29
  <% else %>
30
30
  <%= f.search_field @query_param, value: @q, placeholder: scoped_t('search.placeholder'), class: "search-q q form-control rounded-#{search_fields.length > 1 ? '0' : 'left'}", autofocus: @autofocus, aria: { label: scoped_t('search.label') } %>
@@ -1,10 +1,7 @@
1
- <div class='pagination-search-widgets'>
1
+ <div class="search-context page-links">
2
+ <%= link_to_previous_document %> |
2
3
 
3
- <div class="page-links">
4
- <%= link_to_previous_document %> |
4
+ <%= item_page_entry_info %> |
5
5
 
6
- <%= item_page_entry_info %> |
7
-
8
- <%= link_to_next_document %>
9
- </div>
6
+ <%= link_to_next_document %>
10
7
  </div>
@@ -0,0 +1,7 @@
1
+ <nav id="skip-link" role="navigation" class="visually-hidden-focusable sr-only sr-only-focusable" aria-label="<%= t('blacklight.skip_links.label') %>">
2
+ <div class="container-xl">
3
+ <%= link_to_search %>
4
+ <%= link_to_main %>
5
+ <%= content %>
6
+ </div>
7
+ </nav>
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ class SkipLinkComponent < Blacklight::Component
5
+ def link_to_search
6
+ link_to t('blacklight.skip_links.search_field'), '#search_field', class: link_classes
7
+ end
8
+
9
+ def link_to_main
10
+ link_to t('blacklight.skip_links.main_content'), '#main-container', class: link_classes
11
+ end
12
+
13
+ def link_classes
14
+ 'd-inline-flex p-2 m-1'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ module System
5
+ class DropdownButtonComponent < Blacklight::Component
6
+ def initialize(label:, classes: %w[btn btn-outline-secondary dropdown-toggle])
7
+ @classes = classes
8
+ @label = label
9
+ end
10
+
11
+ def call
12
+ button_tag class: @classes, aria: { expanded: false }, data: { toggle: 'dropdown', 'bs-toggle': 'dropdown' } do
13
+ safe_join([@label, content_tag(:span, '', class: 'caret')])
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -3,11 +3,8 @@
3
3
  module Blacklight
4
4
  module System
5
5
  class DropdownComponent < Blacklight::Component
6
- renders_one :button, (lambda do |classes:, label:|
7
- button_tag class: classes, aria: { expanded: false }, data: { toggle: 'dropdown', 'bs-toggle': 'dropdown' } do
8
- safe_join([label, content_tag(:span, '', class: 'caret')])
9
- end
10
- end)
6
+ renders_one :button, DropdownButtonComponent
7
+
11
8
  renders_many :options, (lambda do |text:, url:, selected: false|
12
9
  link_to(text, url, class: "dropdown-item #{'active' if selected}", role: 'menuitem', aria: { current: ('page' if selected) })
13
10
  end)
@@ -18,7 +15,7 @@ module Blacklight
18
15
  @choices = choices
19
16
  @search_state = search_state
20
17
  @id = id
21
- @classes = classes.concat(['btn-group', "#{param.to_s.parameterize}-dropdown"])
18
+ @classes = classes.push('btn-group', "#{param.to_s.parameterize}-dropdown")
22
19
  @selected = selected || default || option_text_and_value(@choices.first)&.first
23
20
  @interpolation = interpolation
24
21
  end
@@ -29,7 +26,7 @@ module Blacklight
29
26
  end
30
27
 
31
28
  def before_render
32
- with_button(classes: 'btn btn-outline-secondary dropdown-toggle', label: button_label) unless button
29
+ with_button(label: button_label) unless button
33
30
 
34
31
  return if options.any?
35
32
 
@@ -1,4 +1,4 @@
1
- <div class="alert <%= @classes %>">
1
+ <div class="alert alert-dismissible <%= @classes %>">
2
2
  <%= message %>
3
3
  <%= tag.button button_contents, type: "button", class: "btn-close",
4
4
  data: { dismiss: "alert", bs_dismiss: "alert" },
@@ -1,4 +1,4 @@
1
- <nav class="navbar navbar-expand-md navbar-dark bg-dark topbar" role="navigation">
1
+ <nav class="navbar navbar-expand-md navbar-dark bg-dark topbar" aria-label="<%= aria_label %>">
2
2
  <div class="<%= container_classes %>">
3
3
  <%= logo_link %>
4
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">
@@ -9,4 +9,4 @@
9
9
  <%= render 'shared/user_util_links' %>
10
10
  </div>
11
11
  </div>
12
- </nav>
12
+ </nav>
@@ -10,6 +10,10 @@ module Blacklight
10
10
 
11
11
  delegate :application_name, :container_classes, to: :helpers
12
12
 
13
+ def aria_label
14
+ t('blacklight.top_navbar.aria.container_label')
15
+ end
16
+
13
17
  def logo_link(title: application_name)
14
18
  link_to title, blacklight_config.logo_link, class: 'mb-0 navbar-brand navbar-logo'
15
19
  end
@@ -53,11 +53,7 @@ module Blacklight::CatalogHelperBehavior
53
53
  collection.limit_value
54
54
  end
55
55
 
56
- end_num = if collection.offset_value + end_num <= collection.total_count
57
- collection.offset_value + end_num
58
- else
59
- collection.total_count
60
- end
56
+ end_num = [collection.offset_value + end_num, collection.total_count].min
61
57
 
62
58
  case collection.total_count
63
59
  when 0
@@ -109,10 +105,12 @@ module Blacklight::CatalogHelperBehavior
109
105
  ##
110
106
  # Look up the current per page value, or the default if none if set
111
107
  #
108
+ # @deprecated
112
109
  # @return [Integer]
113
110
  def current_per_page
114
111
  (@response.rows if @response && @response.rows > 0) || params.fetch(:per_page, blacklight_config.default_per_page).to_i
115
112
  end
113
+ Blacklight.deprecation.deprecate_methods(self, current_per_page: 'has moved to Blacklight::Search::PerPageComponent')
116
114
 
117
115
  ##
118
116
  # Should we display the sort and per page widget?
@@ -37,6 +37,10 @@ module Blacklight
37
37
  filter_partials(blacklight_config.view_config(:show).document_actions, { document: document }.merge(options)).map { |_k, v| v }
38
38
  end
39
39
 
40
+ def filter_partials(partials, options)
41
+ partials.select { |_, config| blacklight_configuration_context.evaluate_if_unless_configuration config, options }
42
+ end
43
+
40
44
  private
41
45
 
42
46
  def render_filtered_partials(partials, options = {})
@@ -52,9 +56,5 @@ module Blacklight
52
56
  end
53
57
  safe_join(content, "\n") unless block_given?
54
58
  end
55
-
56
- def filter_partials(partials, options)
57
- partials.select { |_, config| blacklight_configuration_context.evaluate_if_unless_configuration config, options }
58
- end
59
59
  end
60
60
  end
@@ -92,6 +92,7 @@ module Blacklight::ConfigurationHelperBehavior
92
92
  end
93
93
 
94
94
  ##
95
+ # @deprecated
95
96
  # The available options for results per page, in the style of #options_for_select
96
97
  def per_page_options_for_select
97
98
  return [] if blacklight_config.per_page.blank?
@@ -100,6 +101,7 @@ module Blacklight::ConfigurationHelperBehavior
100
101
  [t(:'blacklight.search.per_page.label', count: count).html_safe, count]
101
102
  end
102
103
  end
104
+ Blacklight.deprecation.deprecate_methods(self, per_page_options_for_select: 'has moved to Blacklight::Search::PerPageComponent')
103
105
 
104
106
  ##
105
107
  # Determine whether to render a field by evaluating :if and :unless conditions
@@ -41,11 +41,11 @@ module Blacklight
41
41
  end
42
42
 
43
43
  ##
44
- # Class used for specifying main layout container classes. Can be
45
- # overwritten to return 'container-fluid' for Bootstrap full-width layout
44
+ # Class used for specifying main layout container classes.
45
+ # Set config.full_width_layout to true to use a fluid layout.
46
46
  # @return [String]
47
47
  def container_classes
48
- 'container'
48
+ blacklight_config.full_width_layout ? 'container-fluid' : 'container'
49
49
  end
50
50
 
51
51
  ##
@@ -37,7 +37,7 @@ export default class CheckboxSubmit {
37
37
  this.labelTarget.removeAttribute('disabled')
38
38
  this.checkboxTarget.removeAttribute('disabled')
39
39
  this.updateStateFor(!this.checked)
40
- document.querySelector('[data-role=bookmark-counter]').innerHTML = json.bookmarks.count
40
+ if (this.bookmarkCounter()) this.bookmarkCounter().innerHTML = json.bookmarks.count
41
41
  }).catch((error) => {
42
42
  this.handleError(error)
43
43
  })
@@ -63,6 +63,10 @@ export default class CheckboxSubmit {
63
63
  return this.form.querySelector('[data-checkboxsubmit-target="span"]')
64
64
  }
65
65
 
66
+ bookmarkCounter() {
67
+ return document.querySelector('[data-role="bookmark-counter"]')
68
+ }
69
+
66
70
  handleError() {
67
71
  alert("Unable to save the bookmark at this time.")
68
72
  }
@@ -31,7 +31,7 @@ module Blacklight::Document
31
31
  # but extensions should call super and modify hash returned, to avoid
32
32
  # unintentionally erasing values provided by other extensions.
33
33
  def to_semantic_values
34
- @semantic_value_hash ||= self.class.field_semantics.each_with_object(Hash.new([])) do |(key, field_names), hash|
34
+ @semantic_value_hash ||= self.class.field_semantics.each_with_object(Hash.new { |hash, key| hash[key] = [] }) do |(key, field_names), hash|
35
35
  ##
36
36
  # Handles single string field_name or an array of field_names
37
37
  value = Array.wrap(field_names).map { |field_name| self[field_name] }.flatten.compact
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ class FacetCheckboxItemPresenter < Blacklight::FacetItemPresenter
5
+ # Check if the query parameters have any inclusive facets with the given value
6
+ # @return [Boolean]
7
+ def selected?
8
+ search_state.filter(facet_config).values(except: [:filters, :missing]).flatten.include?(value)
9
+ end
10
+ end
11
+ end
@@ -19,7 +19,15 @@ module Blacklight
19
19
  end
20
20
 
21
21
  def active?
22
- search_state.filter(facet_field).any?
22
+ if in_advanced_search?
23
+ search_state.filter(facet_field).values(except: [:filters, :missing]).any?
24
+ else
25
+ search_state.filter(facet_field).any?
26
+ end
27
+ end
28
+
29
+ def in_advanced_search?
30
+ search_state.params[:action] == "advanced_search"
23
31
  end
24
32
 
25
33
  def in_modal?
@@ -148,7 +148,15 @@ module Blacklight
148
148
  .merge(blacklight_config.fetch_many_document_params)
149
149
  .merge(extra_controller_params)
150
150
 
151
- solr_response = repository.search(query)
151
+ # find_many was introduced in Blacklight 8.4. Before that, we used the
152
+ # regular search method (possibly with a find-many specific `qt` parameter).
153
+ # In order to support Repository implementations that may not have a find_many,
154
+ # we'll fall back to search if find_many isn't available.
155
+ solr_response = if repository.respond_to?(:find_many)
156
+ repository.find_many(query)
157
+ else
158
+ repository.search(query)
159
+ end
152
160
 
153
161
  solr_response.documents
154
162
  end
@@ -1,10 +1 @@
1
- <% if show_sort_and_per_page? %>
2
- <span class="sr-only visually-hidden"><%= t('blacklight.search.per_page.title') %></span>
3
- <%= render(Blacklight::System::DropdownComponent.new(
4
- param: :per_page,
5
- choices: per_page_options_for_select,
6
- id: 'per_page-dropdown',
7
- search_state: search_state,
8
- selected: current_per_page,
9
- interpolation: :count)) %>
10
- <% end %>
1
+ <%= render Blacklight::Search::PerPageComponent.new(search_state:, blacklight_config:, response: @response) %>
@@ -8,7 +8,7 @@
8
8
  <% end %>
9
9
 
10
10
  <% content_for(:skip_links) do -%>
11
- <%= link_to t('blacklight.skip_links.first_result'), '#documents', class: 'element-invisible element-focusable rounded-bottom py-2 px-3', data: { turbolinks: 'false' } %>
11
+ <%= link_to t('blacklight.skip_links.first_result'), '#documents', class: 'd-inline-flex p-2 m-1', data: { turbolinks: 'false' } %>
12
12
  <% end %>
13
13
 
14
14
  <% content_for(:container_header) do -%>
@@ -1,4 +1,4 @@
1
- <%= render blacklight_config.track_search_session.item_pagination_component.new(search_context: @search_context, search_session: search_session, current_document: @document) if blacklight_config.track_search_session.item_pagination_component %>
1
+ <%= render blacklight_config.view_config(:show).document_header_component.new(document: @document, search_context: @search_context, search_session: search_session) %>
2
2
  <% @page_title = t('blacklight.search.show.title', document_title: document_presenter(@document).html_title, application_name: application_name).html_safe %>
3
3
  <% content_for(:head) { render_link_rel_alternates } %>
4
4
 
@@ -1,5 +1,3 @@
1
- <%= render blacklight_config.track_search_session.applied_params_component.new if blacklight_config.track_search_session.applied_params_component %>
2
-
3
1
  <%= render 'show_main_content' %>
4
2
 
5
3
  <% content_for(:sidebar) do %>
@@ -1,3 +1,3 @@
1
1
  <% @suggestions.each do |suggestion| %>
2
- <li role="option"><span><%= suggestion['term'] %></span></li>
2
+ <li role="option" class="dropdown-item"><span><%= suggestion['term'] %></span></li>
3
3
  <% end %>
@@ -8,12 +8,18 @@
8
8
  remote: data-remote
9
9
  -%>
10
10
  <% page_display = number_with_delimiter(page.to_s) %>
11
-
12
- <li class="page-item <%= 'active' if page.current? %>">
13
- <% if page.current? %>
14
- <span class="page-link" aria-current="true"><%= page_display %><span class="sr-only visually-hidden"> <%= t('views.pagination.aria.current_page', page: page_display) %></span></span>
15
- <% else %>
16
- <%= link_to page_display, url, :remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil, class: 'page-link', aria: { label: t('views.pagination.aria.go_to_page', page: page_display) } %>
11
+ <% link_attrs = {
12
+ remote: remote,
13
+ rel: page.next? ? 'next' : page.prev? ? 'prev' : nil,
14
+ class: 'page-link',
15
+ }
16
+ %>
17
+ <% if page.current? %>
18
+ <%= tag.li class: class_names('page-item', 'active'), aria_current: 'page' do %>
19
+ <%= link_to page_display, url, link_attrs.merge(aria: { label: t('views.pagination.aria.current_page', page: page_display) }) %>
17
20
  <% end %>
18
- </li>
19
-
21
+ <% else %>
22
+ <%= tag.li class: 'page-item' do %>
23
+ <%= link_to page_display, url, link_attrs.merge(aria: { label: t('views.pagination.aria.go_to_page', page: page_display) }) %>
24
+ <% end %>
25
+ <% end %>