blacklight 8.2.2 → 8.4.0

Sign up to get free protection for your applications and to get access to all the features.
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 %>