blacklight 8.10.1 → 9.0.0.beta1

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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/.env +3 -3
  3. data/.github/pull_request_template.md +7 -0
  4. data/.github/workflows/ruby.yml +98 -0
  5. data/.rubocop.yml +2 -2
  6. data/.rubocop_todo.yml +0 -9
  7. data/README.md +30 -8
  8. data/VERSION +1 -1
  9. data/app/assets/builds/blacklight.css +448 -0
  10. data/app/assets/javascripts/blacklight/blacklight.esm.js +8 -40
  11. data/app/assets/javascripts/blacklight/blacklight.esm.js.map +1 -1
  12. data/app/assets/javascripts/blacklight/blacklight.js +8 -40
  13. data/app/assets/javascripts/blacklight/blacklight.js.map +1 -1
  14. data/app/assets/stylesheets/blacklight/_balanced_list.scss +1 -4
  15. data/app/assets/stylesheets/blacklight/_blacklight_base.scss +1 -3
  16. data/app/assets/stylesheets/blacklight/_bookmark.scss +44 -41
  17. data/app/assets/stylesheets/blacklight/_bootstrap_overrides.scss +0 -29
  18. data/app/assets/stylesheets/blacklight/_constraints.scss +15 -24
  19. data/app/assets/stylesheets/blacklight/_controls.scss +2 -18
  20. data/app/assets/stylesheets/blacklight/_facets.scss +15 -82
  21. data/app/assets/stylesheets/blacklight/_group.scss +2 -5
  22. data/app/assets/stylesheets/blacklight/_header.scss +4 -11
  23. data/app/assets/stylesheets/blacklight/_icons.scss +0 -8
  24. data/app/assets/stylesheets/blacklight/_modal.scss +9 -10
  25. data/app/assets/stylesheets/blacklight/_pagination.scss +3 -5
  26. data/app/assets/stylesheets/blacklight/_search_form.scss +0 -1
  27. data/app/assets/stylesheets/blacklight/_search_history.scss +0 -4
  28. data/app/assets/stylesheets/blacklight/_search_results.scss +1 -15
  29. data/app/assets/stylesheets/blacklight/blacklight_defaults.scss +9 -17
  30. data/app/assets/stylesheets/blacklight/build.scss +4 -0
  31. data/app/components/blacklight/advanced_search_form_component.rb +1 -1
  32. data/app/components/blacklight/constraint_component.rb +1 -1
  33. data/app/components/blacklight/constraint_layout_component.html.erb +2 -2
  34. data/app/components/blacklight/constraints_component.html.erb +2 -2
  35. data/app/components/blacklight/constraints_component.rb +1 -1
  36. data/app/components/blacklight/document/action_component.rb +3 -1
  37. data/app/components/blacklight/document/bookmark_component.html.erb +3 -3
  38. data/app/components/blacklight/document/group_component.html.erb +1 -1
  39. data/app/components/blacklight/document/page_header_component.rb +1 -1
  40. data/app/components/blacklight/document/sidebar_component.rb +5 -5
  41. data/app/components/blacklight/document_component.rb +9 -13
  42. data/app/components/blacklight/document_title_component.rb +3 -2
  43. data/app/components/blacklight/facet_field_component.html.erb +5 -5
  44. data/app/components/blacklight/facet_field_list_component.rb +4 -22
  45. data/app/components/blacklight/facet_field_pagination_component.html.erb +2 -2
  46. data/app/components/blacklight/facet_item_component.rb +2 -2
  47. data/app/components/blacklight/facet_item_pivot_component.rb +2 -2
  48. data/app/components/blacklight/response/facet_group_component.html.erb +3 -18
  49. data/app/components/blacklight/response/facet_group_component.rb +7 -23
  50. data/app/components/blacklight/response/facet_toggle_button_component.html.erb +16 -0
  51. data/app/components/blacklight/response/facet_toggle_button_component.rb +14 -0
  52. data/app/components/blacklight/response/pagination_component.html.erb +1 -1
  53. data/app/components/blacklight/response/pagination_component.rb +2 -1
  54. data/app/components/blacklight/response/sort_component.rb +1 -0
  55. data/app/components/blacklight/response/view_type_button_component.html.erb +1 -1
  56. data/app/components/blacklight/response/view_type_component.html.erb +1 -1
  57. data/app/components/blacklight/search/facet_suggest_input.html.erb +7 -10
  58. data/app/components/blacklight/search/facet_suggest_input.rb +0 -4
  59. data/app/components/blacklight/search/per_page_component.html.erb +1 -1
  60. data/app/components/blacklight/search/per_page_component.rb +1 -0
  61. data/app/components/blacklight/search/sidebar_component.html.erb +1 -1
  62. data/app/components/blacklight/search/sidebar_component.rb +1 -1
  63. data/app/components/blacklight/search_bar_component.html.erb +3 -3
  64. data/app/components/blacklight/search_bar_component.rb +2 -2
  65. data/app/components/blacklight/search_button_component.rb +2 -2
  66. data/app/components/blacklight/search_context/server_applied_params_component.html.erb +2 -2
  67. data/app/components/blacklight/search_context/server_applied_params_component.rb +9 -0
  68. data/app/components/blacklight/skip_link_component.html.erb +1 -1
  69. data/app/components/blacklight/skip_link_component.rb +7 -3
  70. data/app/components/blacklight/skip_link_item_component.rb +18 -0
  71. data/app/components/blacklight/system/dropdown_component.html.erb +1 -1
  72. data/app/components/blacklight/system/dropdown_component.rb +1 -1
  73. data/app/components/blacklight/top_navbar_component.html.erb +1 -1
  74. data/app/controllers/concerns/blacklight/catalog.rb +3 -2
  75. data/app/controllers/concerns/blacklight/search_context.rb +1 -13
  76. data/app/helpers/blacklight/blacklight_helper_behavior.rb +0 -6
  77. data/app/helpers/blacklight/catalog_helper_behavior.rb +1 -11
  78. data/app/helpers/blacklight/configuration_helper_behavior.rb +0 -12
  79. data/app/helpers/blacklight/document_helper_behavior.rb +0 -26
  80. data/app/helpers/blacklight/icon_helper_behavior.rb +1 -9
  81. data/app/helpers/blacklight/layout_helper_behavior.rb +2 -2
  82. data/app/helpers/blacklight/render_partials_helper_behavior.rb +0 -14
  83. data/app/helpers/blacklight/url_helper_behavior.rb +1 -1
  84. data/app/javascript/{blacklight → blacklight-frontend}/bookmark_toggle.js +1 -1
  85. data/app/javascript/{blacklight → blacklight-frontend}/core.js +2 -10
  86. data/app/javascript/{blacklight → blacklight-frontend}/debounce.js +1 -1
  87. data/app/javascript/blacklight-frontend/facet_suggest.js +26 -0
  88. data/app/javascript/blacklight-frontend/index.js +18 -0
  89. data/app/javascript/{blacklight → blacklight-frontend}/modal.js +2 -3
  90. data/app/javascript/{blacklight → blacklight-frontend}/search_context.js +2 -3
  91. data/app/models/concerns/blacklight/document.rb +0 -11
  92. data/app/models/concerns/blacklight/user.rb +1 -1
  93. data/app/presenters/blacklight/facet_field_presenter.rb +2 -2
  94. data/app/presenters/blacklight/json_presenter.rb +3 -1
  95. data/app/services/blacklight/search_params_yaml_coder.rb +0 -2
  96. data/app/views/bookmarks/_clear_bookmarks_widget.html.erb +0 -2
  97. data/app/views/bookmarks/index.html.erb +1 -1
  98. data/app/views/catalog/_results_pagination.html.erb +2 -5
  99. data/app/views/catalog/_search_results.html.erb +4 -4
  100. data/app/views/catalog/_search_results_header.html.erb +1 -1
  101. data/app/views/catalog/_sort_and_per_page.html.erb +1 -1
  102. data/app/views/catalog/_sort_widget.html.erb +1 -0
  103. data/app/views/catalog/facet.html.erb +9 -9
  104. data/app/views/catalog/show.html.erb +2 -3
  105. data/app/views/kaminari/blacklight/_paginator.html.erb +1 -2
  106. data/app/views/layouts/blacklight/base.html.erb +3 -7
  107. data/app/views/search_history/index.html.erb +0 -2
  108. data/blacklight.gemspec +4 -4
  109. data/config/importmap.rb +1 -1
  110. data/config/locales/blacklight.ar.yml +4 -4
  111. data/config/locales/blacklight.ca.yml +124 -124
  112. data/config/locales/blacklight.de.yml +2 -2
  113. data/config/locales/blacklight.en.yml +14 -14
  114. data/config/locales/blacklight.es.yml +4 -4
  115. data/config/locales/blacklight.fr.yml +4 -4
  116. data/config/locales/blacklight.hu.yml +4 -4
  117. data/config/locales/blacklight.it.yml +3 -3
  118. data/config/locales/blacklight.nl.yml +3 -3
  119. data/config/locales/blacklight.pt-BR.yml +3 -3
  120. data/config/locales/blacklight.sq.yml +4 -4
  121. data/config/locales/blacklight.zh.yml +4 -4
  122. data/lib/blacklight/configuration/display_field.rb +1 -1
  123. data/lib/blacklight/configuration/fields.rb +3 -3
  124. data/lib/blacklight/configuration/view_config.rb +0 -2
  125. data/lib/blacklight/configuration.rb +7 -12
  126. data/lib/blacklight/engine.rb +0 -6
  127. data/lib/blacklight/open_struct_with_hash_access.rb +4 -4
  128. data/lib/blacklight/search_builder.rb +4 -4
  129. data/lib/blacklight/search_state/filter_field.rb +2 -2
  130. data/lib/blacklight/solr/request.rb +1 -7
  131. data/lib/blacklight/solr/response/group_response.rb +2 -2
  132. data/lib/blacklight.rb +1 -1
  133. data/lib/generators/blacklight/assets/importmap_generator.rb +8 -24
  134. data/lib/generators/blacklight/assets/propshaft_generator.rb +1 -1
  135. data/lib/generators/blacklight/assets_generator.rb +3 -3
  136. data/lib/generators/blacklight/controller_generator.rb +3 -3
  137. data/lib/generators/blacklight/user_generator.rb +9 -10
  138. data/package.json +14 -4
  139. data/rollup.config.js +1 -1
  140. data/spec/components/blacklight/document/action_component_spec.rb +1 -5
  141. data/spec/components/blacklight/document/sidebar_component_spec.rb +5 -20
  142. data/spec/components/blacklight/facet_field_checkboxes_component_spec.rb +2 -2
  143. data/spec/components/blacklight/facet_field_list_component_spec.rb +2 -2
  144. data/spec/components/blacklight/search/facet_suggest_input_spec.rb +3 -27
  145. data/spec/components/blacklight/search_bar_component_spec.rb +1 -1
  146. data/spec/controllers/catalog_controller_spec.rb +1 -1
  147. data/spec/features/axe_spec.rb +6 -11
  148. data/spec/features/bookmarks_spec.rb +48 -11
  149. data/spec/features/facets_spec.rb +22 -90
  150. data/spec/features/search_context_spec.rb +1 -2
  151. data/spec/features/search_filters_spec.rb +6 -6
  152. data/spec/helpers/blacklight/configuration_helper_behavior_spec.rb +0 -9
  153. data/spec/helpers/blacklight/render_partials_helper_behavior_spec.rb +1 -1
  154. data/spec/lib/blacklight/parameters_spec.rb +1 -12
  155. data/spec/lib/blacklight/search_state/filter_field_spec.rb +0 -18
  156. data/spec/models/blacklight/solr/request_spec.rb +7 -0
  157. data/spec/services/blacklight/search_service_spec.rb +1 -1
  158. data/spec/views/catalog/_facet_layout.html.erb_spec.rb +3 -3
  159. data/spec/views/catalog/facet.html.erb_spec.rb +0 -8
  160. data/spec/views/catalog/index.html.erb_spec.rb +6 -3
  161. data/spec/views/catalog/show.html.erb_spec.rb +1 -0
  162. data/tasks/blacklight.rake +8 -5
  163. metadata +31 -61
  164. data/.github/matrix.json +0 -78
  165. data/.github/workflows/build.yml +0 -16
  166. data/.github/workflows/lint.yml +0 -25
  167. data/.github/workflows/main.yml +0 -24
  168. data/.github/workflows/test.yml +0 -58
  169. data/app/assets/stylesheets/blacklight/_autocomplete.scss +0 -25
  170. data/app/assets/stylesheets/blacklight/_mixins.scss +0 -20
  171. data/app/components/blacklight/icons/legacy_icon_component.rb +0 -30
  172. data/app/javascript/blacklight/facet_suggest.js +0 -48
  173. data/app/javascript/blacklight/index.js +0 -18
  174. data/app/views/catalog/_constraints.html.erb +0 -1
  175. data/app/views/catalog/_facets.html.erb +0 -5
  176. data/app/views/catalog/_search_form.html.erb +0 -7
  177. data/app/views/catalog/_search_header.html.erb +0 -1
  178. data/app/views/catalog/_show_sidebar.html.erb +0 -3
  179. data/app/views/catalog/_show_tools.html.erb +0 -2
  180. data/app/views/catalog/_start_over.html.erb +0 -1
  181. data/app/views/shared/_header_navbar.html.erb +0 -1
  182. data/lib/generators/blacklight/assets/sprockets_generator.rb +0 -68
  183. data/spec/components/blacklight/system/dropdown_component_spec.rb +0 -26
  184. data/spec/views/catalog/_search_header.erb_spec.rb +0 -14
  185. data/spec/views/catalog/_show_sidebar.erb_spec.rb +0 -24
  186. data/spec/views/catalog/_show_tools.html.erb_spec.rb +0 -37
  187. /data/app/javascript/{blacklight → blacklight-frontend}/button_focus.js +0 -0
  188. /data/app/javascript/{blacklight → blacklight-frontend}/checkbox_submit.js +0 -0
  189. /data/app/javascript/{blacklight → blacklight-frontend}/modalForm.js +0 -0
@@ -6,7 +6,7 @@ module Blacklight
6
6
  renders_one :button, DropdownButtonComponent
7
7
 
8
8
  renders_many :options, (lambda do |text:, url:, selected: false|
9
- link_to(text, url, class: "dropdown-item #{'active' if selected}", aria: { current: ('page' if selected) })
9
+ link_to(text, url, class: "dropdown-item #{'active' if selected}", role: 'menuitem', aria: { current: ('page' if selected) })
10
10
  end)
11
11
 
12
12
  # rubocop:disable Metrics/ParameterLists
@@ -1,7 +1,7 @@
1
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
- <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
 
@@ -83,10 +83,11 @@ module Blacklight::Catalog
83
83
  @facet = blacklight_config.facet_fields[params[:id]]
84
84
  raise ActionController::RoutingError, 'Not Found' unless @facet
85
85
 
86
- @response = if params[:query_fragment].present?
86
+ query_fragment = params[:query_fragment] || ''
87
+ @response = if query_fragment.present?
87
88
  search_service.facet_suggest_response(@facet.key, params[:query_fragment])
88
89
  else
89
- search_service.facet_field_response(@facet.key)
90
+ @response = search_service.facet_field_response(@facet.key)
90
91
  end
91
92
  @display_facet = @response.aggregations[@facet.field]
92
93
 
@@ -40,7 +40,7 @@ module Blacklight::SearchContext
40
40
  @page_link_data[:prev] = page_links_document_path(documents.first, index)
41
41
  @page_link_data[:next] = page_links_document_path(documents.last, index + 2)
42
42
  end
43
- if response&.total&.positive?
43
+ if response&.total && response.total.positive?
44
44
  @page_link_data[:counterRaw] = counter_param
45
45
  @page_link_data[:counterDelimited] = helpers.number_with_delimiter(counter_param.to_i)
46
46
  @page_link_data[:totalRaw] = response.total
@@ -133,21 +133,9 @@ module Blacklight::SearchContext
133
133
 
134
134
  # A list of query parameters that should not be persisted for a search
135
135
  def nonpersisted_search_session_params
136
- unless method(:blacklisted_search_session_params).source_location.first.end_with?('deprecation/method_wrappers.rb')
137
- # The blacklisted_search_session_params was overridden, so call it.
138
- Blacklight.deprecation.warn(self, "blacklisted_search_session_params was overriden in your app, " \
139
- "but that method should be renamed to `nonpersisted_search_session_params'. " \
140
- "The original behavior will be removed in the next major release.")
141
- return blacklisted_search_session_params
142
- end
143
136
  [:commit, :counter, :total, :search_id, :page, :per_page]
144
137
  end
145
138
 
146
- def blacklisted_search_session_params
147
- nonpersisted_search_session_params
148
- end
149
- Blacklight.deprecation.deprecate_methods(self, blacklisted_search_session_params: 'use nonpersisted_search_session_params instead')
150
-
151
139
  # calls setup_previous_document then setup_next_document.
152
140
  # used in the show action for single view pagination.
153
141
  def setup_next_and_previous_documents
@@ -41,10 +41,4 @@ module Blacklight::BlacklightHelperBehavior
41
41
  def self.blacklight_gem_path
42
42
  @blacklight_gem_path ||= Gem.loaded_specs["blacklight"].full_gem_path
43
43
  end
44
-
45
- def partial_from_blacklight?(partial)
46
- path = lookup_context.find_all(partial, lookup_context.prefixes + [""], true).first&.identifier
47
-
48
- path.nil? ? false : path.starts_with?(Blacklight::BlacklightHelperBehavior.blacklight_gem_path)
49
- end
50
44
  end
@@ -102,16 +102,6 @@ module Blacklight::CatalogHelperBehavior
102
102
  (blacklight_config.sort_fields.values.find { |f| f.sort == @response.sort } if @response && @response.sort.present?) || blacklight_config.sort_fields[params[:sort]] || default_sort_field
103
103
  end
104
104
 
105
- ##
106
- # Look up the current per page value, or the default if none if set
107
- #
108
- # @deprecated
109
- # @return [Integer]
110
- def current_per_page
111
- (@response.rows if @response && @response.rows > 0) || params.fetch(:per_page, blacklight_config.default_per_page).to_i
112
- end
113
- Blacklight.deprecation.deprecate_methods(self, current_per_page: 'has moved to Blacklight::Search::PerPageComponent')
114
-
115
105
  ##
116
106
  # Should we display the sort and per page widget?
117
107
  #
@@ -197,7 +187,7 @@ module Blacklight::CatalogHelperBehavior
197
187
  # Get the current "view type" (and ensure it is a valid type)
198
188
  #
199
189
  # @param [Hash] query_params the query parameters to check
200
- # @return [Symbol]
190
+ # @return [Symbol] (e.g. :index, :gallery)
201
191
  def document_index_view_type query_params = params || {}
202
192
  view_param = query_params[:view]
203
193
  view_param ||= session[:preferred_view] if respond_to?(:session)
@@ -91,18 +91,6 @@ module Blacklight::ConfigurationHelperBehavior
91
91
  (active_sort_fields.find { |_k, config| config.respond_to?(:default) && config.default } || active_sort_fields.first)&.last
92
92
  end
93
93
 
94
- ##
95
- # @deprecated
96
- # The available options for results per page, in the style of #options_for_select
97
- def per_page_options_for_select
98
- return [] if blacklight_config.per_page.blank?
99
-
100
- blacklight_config.per_page.map do |count|
101
- [t(:'blacklight.search.per_page.label', count: count).html_safe, count]
102
- end
103
- end
104
- Blacklight.deprecation.deprecate_methods(self, per_page_options_for_select: 'has moved to Blacklight::Search::PerPageComponent')
105
-
106
94
  ##
107
95
  # Determine whether to render a field by evaluating :if and :unless conditions
108
96
  #
@@ -24,32 +24,6 @@ module Blacklight::DocumentHelperBehavior
24
24
  'blacklight-'
25
25
  end
26
26
 
27
- ##
28
- # Render the sidebar partial for a document
29
- # This is used as an integration point by downstream apps to add to the
30
- # default sidebar.
31
- # See: https://github.com/geoblacklight/geoblacklight/blob/7d3c31c7af3362879b97e2c1351a2496c728c59c/app/helpers/blacklight_helper.rb#L7
32
- #
33
- # @param [SolrDocument] document
34
- # @deprecated
35
- # @return [String]
36
- def render_document_sidebar_partial(document)
37
- unless @render_document_sidebar_partials_deprecation_warning_shown
38
- partials = lookup_context.find_all('show_sidebar', lookup_context.prefixes, true, [], {})
39
- unless partials.first.identifier.starts_with? Blacklight.root
40
- Blacklight.deprecation.warn('The partial catalog/_show_sidebar.html.erb will not be rendered by #render_document_sidebar_partial in Blacklight 9.0.' \
41
- 'Configure blacklight_config.show.sidebar_component instead (default Blacklight::Search::SidebarComponent).')
42
- @render_document_sidebar_partials_deprecation_warning_shown = true
43
- end
44
- end
45
-
46
- render 'show_sidebar', document: document
47
- end
48
-
49
- Blacklight.deprecation.deprecate_methods(self,
50
- render_document_sidebar_partial: 'has been replaced by calling the sidebar component (Blacklight::Search::SidebarComponent) directly. ' \
51
- 'Set sidebar_component in the view config.')
52
-
53
27
  ##
54
28
  # return the Bookmarks on a set of documents (all bookmarks on the page)
55
29
  # @private
@@ -4,18 +4,10 @@
4
4
  # Module to help generate icon helpers for SVG images
5
5
  module Blacklight::IconHelperBehavior
6
6
  ##
7
- # Returns the raw SVG (String) for a Blacklight Icon located in
8
- # app/assets/images/blacklight/*.svg. Caches them so we don't have to look up
9
- # the svg everytime.
7
+ # Returns the raw SVG (String) for a Blacklight Icon
10
8
  # @param [String, Symbol] icon_name
11
9
  # @return [String]
12
10
  def blacklight_icon(icon_name, **kwargs)
13
11
  render "Blacklight::Icons::#{icon_name.to_s.camelize}Component".constantize.new(**kwargs)
14
- rescue NameError
15
- Blacklight.deprecation.warn(
16
- "Falling back on the LegacyIconComponent with \"#{icon_name}\" is deprecated. Instead create the component `Blacklight::Icons::#{icon_name.to_s.camelize}Component` for this icon."
17
- )
18
-
19
- render Blacklight::Icons::LegacyIconComponent.new(name: icon_name, **kwargs)
20
12
  end
21
13
  end
@@ -55,8 +55,8 @@ module Blacklight
55
55
  #
56
56
  # @param [Hash] options
57
57
  # @return [String]
58
- def render_nav_actions(options = {}, &block)
59
- render_filtered_partials(blacklight_config.navbar.partials, options, &block)
58
+ def render_nav_actions(options = {}, &)
59
+ render_filtered_partials(blacklight_config.navbar.partials, options, &)
60
60
  end
61
61
 
62
62
  ##
@@ -11,20 +11,6 @@ module Blacklight::RenderPartialsHelperBehavior
11
11
  render_document_index_with_view(document_index_view_type, documents, locals)
12
12
  end
13
13
 
14
- ##
15
- # Return the list of partials for a given solr document
16
- # @param [SolrDocument] doc solr document to render partials for
17
- # @param [Array<String>] partials list of partials to render
18
- # @param [Hash] locals local variables to pass to the render call
19
- # @return [String]
20
- def render_document_partials(doc, partials = [], locals = {})
21
- safe_join(partials.map do |action_name|
22
- render_document_partial(doc, action_name, locals)
23
- end, "\n")
24
- end
25
- Blacklight.deprecation.deprecate_methods(self, render_document_partials: 'Replace this call with: "document_component = blacklight_config.view_config(:atom).summary_component
26
- render document_component.new(presenter: document_presenter(document), component: :div, show: true)"')
27
-
28
14
  ##
29
15
  # Return the list of xml for a given solr document. Doesn't safely escape for HTML.
30
16
  # @param [SolrDocument] doc solr document to render partials for
@@ -114,6 +114,6 @@ module Blacklight::UrlHelperBehavior
114
114
  # Use in e.g. the search history display, where we want something more like text instead of the normal constraints
115
115
  def link_to_previous_search(params)
116
116
  search_state = controller.search_state_class.new(params, blacklight_config, self)
117
- link_to(render(Blacklight::ConstraintsComponent.for_search_history(search_state: search_state)), search_action_path(params))
117
+ link_to(render(Blacklight::ConstraintsComponent.for_search_history(search_state: search_state, classes: 'clearfix constraints-container mb-0')), search_action_path(params))
118
118
  end
119
119
  end
@@ -1,4 +1,4 @@
1
- import CheckboxSubmit from 'blacklight/checkbox_submit'
1
+ import CheckboxSubmit from 'blacklight-frontend/checkbox_submit'
2
2
 
3
3
  const BookmarkToggle = (e) => {
4
4
  if (e.target.matches('[data-checkboxsubmit-target="checkbox"]')) {
@@ -15,14 +15,6 @@ const Core = function() {
15
15
  const listeners = [];
16
16
  if (typeof Turbo !== 'undefined') {
17
17
  listeners.push('turbo:load', 'turbo:frame-load');
18
- } else if (typeof Turbolinks !== 'undefined' && Turbolinks.supported) {
19
- // Turbolinks 5
20
- if (Turbolinks.BrowserAdapter) {
21
- listeners.push('turbolinks:load');
22
- } else {
23
- // Turbolinks < 5
24
- listeners.push('page:load', 'DOMContentLoaded');
25
- }
26
18
  } else {
27
19
  listeners.push('DOMContentLoaded');
28
20
  }
@@ -32,8 +24,8 @@ const Core = function() {
32
24
  };
33
25
  }();
34
26
 
35
- // turbolinks triggers page:load events on page transition
36
- // If app isn't using turbolinks, this event will never be triggered, no prob.
27
+ // turbo triggers turbo:load events on page transition
28
+ // If app isn't using turbo, this event will never be triggered, no prob.
37
29
  Core.listeners().forEach(function(listener) {
38
30
  document.addEventListener(listener, function() {
39
31
  Core.activate()
@@ -3,7 +3,7 @@
3
3
  // const basicFunction = (entry) => console.log(entry)
4
4
  // const debounced = debounce(basicFunction("I should only be called once"));
5
5
  //
6
- // debounced // does NOT print to the screen because it is invoked again less than 200 milliseconds later
6
+ // debounced // does NOT print to the screen becase it is invoked again less than 200 milliseconds later
7
7
  // debounced // does print to the screen
8
8
  // ```
9
9
  export default function debounce(func, timeout = 200) {
@@ -0,0 +1,26 @@
1
+ import debounce from "blacklight-frontend/debounce";
2
+
3
+ const FacetSuggest = async (e) => {
4
+ if (e.target.matches('.facet-suggest')) {
5
+ const queryFragment = e.target.value?.trim();
6
+ const facetField = e.target.dataset.facetField;
7
+ if (!facetField) { return; }
8
+
9
+ const urlToFetch = `/catalog/facet_suggest/${facetField}/${queryFragment}${window.location.search}`
10
+ const response = await fetch(urlToFetch);
11
+ if (response.ok) {
12
+ const blob = await response.blob()
13
+ const text = await blob.text()
14
+
15
+ const facetArea = document.querySelector('.facet-extended-list');
16
+
17
+ if (text && facetArea) {
18
+ facetArea.innerHTML = text
19
+ }
20
+ }
21
+ }
22
+ };
23
+
24
+ document.addEventListener('input', debounce(FacetSuggest));
25
+
26
+ export default FacetSuggest
@@ -0,0 +1,18 @@
1
+ import BookmarkToggle from 'blacklight-frontend/bookmark_toggle'
2
+ import ButtonFocus from 'blacklight-frontend/button_focus'
3
+ import FacetSuggest from 'blacklight-frontend/facet_suggest'
4
+ import Modal from 'blacklight-frontend/modal'
5
+ import ModalForm from 'blacklight-frontend/modalForm'
6
+ import SearchContext from 'blacklight-frontend/search_context'
7
+ import Core from 'blacklight-frontend/core'
8
+
9
+ export default {
10
+ BookmarkToggle,
11
+ ButtonFocus,
12
+ FacetSuggest,
13
+ Modal,
14
+ ModalForm,
15
+ SearchContext,
16
+ Core,
17
+ onLoad: Core.onLoad
18
+ }
@@ -113,7 +113,7 @@ const Modal = (() => {
113
113
  }
114
114
  elements.forEach((el) => frag.appendChild(el))
115
115
  modal.activateScripts(frag)
116
-
116
+
117
117
  modal.target().querySelector('.modal-content').replaceChildren(frag)
118
118
 
119
119
  // send custom event with the modal dialog div as the target
@@ -122,7 +122,6 @@ const Modal = (() => {
122
122
 
123
123
  // if they did preventDefault, don't show the dialog
124
124
  if (e.defaultPrevented) return;
125
-
126
125
  modal.show();
127
126
  };
128
127
 
@@ -138,7 +137,7 @@ const Modal = (() => {
138
137
 
139
138
  modal.modalAjaxLinkClick = function(e) {
140
139
  e.preventDefault();
141
- const href = e.target.closest('a').getAttribute('href')
140
+ const href = e.target.getAttribute('href')
142
141
  fetch(href)
143
142
  .then(response => {
144
143
  if (!response.ok) {
@@ -1,7 +1,6 @@
1
1
  const SearchContext = (e) => {
2
- const contextLink = e.target.closest('[data-context-href]')
3
- if (contextLink) {
4
- SearchContext.handleSearchContextMethod.call(contextLink, e)
2
+ if (e.target.matches('[data-context-href]')) {
3
+ SearchContext.handleSearchContextMethod.call(e.target, e)
5
4
  }
6
5
  }
7
6
 
@@ -31,17 +31,6 @@ module Blacklight::Document
31
31
  class_attribute :inspector_fields, default: [:_source]
32
32
  end
33
33
 
34
- Email = Module.new do
35
- def self.included(mod)
36
- Blacklight.deprecation.warn("Blacklight::Document::Email is deprecated and will be removed (included in #{mod}).")
37
- end
38
- end
39
- Sms = Module.new do
40
- def self.included(mod)
41
- Blacklight.deprecation.warn("Blacklight::Document::Sms is deprecated and will be removed (included in #{mod}).")
42
- end
43
- end
44
-
45
34
  attr_reader :response, :_source
46
35
  alias_method :solr_response, :response
47
36
 
@@ -5,7 +5,7 @@ module Blacklight::User
5
5
  # SEE ALSO: The lib/blacklight/generator/user_generator.rb class for where this
6
6
  # is generated into the hosting application.
7
7
  included do
8
- class_attribute :string_display_key
8
+ class_attribute :string_display_key, default: :email
9
9
 
10
10
  has_many :bookmarks, dependent: :destroy, as: :user
11
11
  has_many :searches, dependent: :destroy, as: :user
@@ -50,8 +50,8 @@ module Blacklight
50
50
  end
51
51
 
52
52
  # Appease rubocop rules by implementing #each_value
53
- def each_value(&block)
54
- values.each(&block)
53
+ def each_value(&)
54
+ values.each(&)
55
55
  end
56
56
 
57
57
  def paginator
@@ -13,7 +13,9 @@ module Blacklight
13
13
 
14
14
  delegate :facet_field_names, :facet_configuration_for_field, to: :blacklight_config
15
15
 
16
- delegate :documents, to: :@response
16
+ def documents
17
+ @response.documents
18
+ end
17
19
 
18
20
  # @return [Array<Blacklight::Solr::Response::Facets::FacetField>]
19
21
  def search_facets
@@ -21,7 +21,6 @@ module Blacklight
21
21
  params.with_indifferent_access
22
22
  end
23
23
 
24
- # rubocop:disable Security/YAMLLoad
25
24
  if YAML.respond_to?(:unsafe_load)
26
25
  def self.yaml_load(payload)
27
26
  if ActiveRecord.try(:use_yaml_unsafe_load) || ActiveRecord::Base.try(:use_yaml_unsafe_load)
@@ -43,6 +42,5 @@ module Blacklight
43
42
  end
44
43
  end
45
44
  end
46
- # rubocop:enable Security/YAMLLoad
47
45
  end
48
46
  end
@@ -1,7 +1,5 @@
1
1
  <%= link_to t('blacklight.bookmarks.clear.action_title'), clear_bookmarks_path,
2
- method: :delete, # for rails-UJS
3
2
  data: {
4
- confirm: t('blacklight.bookmarks.clear.action_confirm'), # for rails-UJS
5
3
  turbo_method: :delete,
6
4
  turbo_confirm: t('blacklight.bookmarks.clear.action_confirm')
7
5
  },
@@ -13,7 +13,7 @@
13
13
  <% else %>
14
14
  <%= render 'sort_and_per_page' %>
15
15
  <%= render partial: 'tools', locals: { document_list: @response.documents } %>
16
- <h2 class='section-heading sr-only visually-hidden'><%= t('blacklight.bookmarks.list_title') %></h2>
16
+ <h2 class='section-heading visually-hidden'><%= t('blacklight.bookmarks.list_title') %></h2>
17
17
  <%= render_document_index @response.documents %>
18
18
  <%= render 'results_pagination' %>
19
19
  <% end %>
@@ -1,7 +1,4 @@
1
1
  <% if show_pagination? and @response.total_pages > 1 %>
2
- <div class="row record-padding">
3
- <div class="col-md-12">
4
- <%= render Blacklight::Response::PaginationComponent.new(response: @response) %>
5
- </div>
6
- </div>
2
+ <%= render Blacklight::Response::PaginationComponent.new(response: @response,
3
+ classes: 'paginate-section mt-2') %>
7
4
  <% end %>
@@ -8,17 +8,17 @@
8
8
  <% end %>
9
9
 
10
10
  <% content_for(:skip_links) do -%>
11
- <%= link_to t('blacklight.skip_links.first_result'), '#documents', class: 'd-inline-flex p-2 m-1', data: { turbolinks: 'false' } %>
11
+ <%= render Blacklight::SkipLinkItemComponent.new(text: t('blacklight.skip_links.first_result'), href: '#documents') %>
12
12
  <% end %>
13
13
 
14
14
  <% content_for(:container_header) do -%>
15
15
  <%= render 'search_results_header' %>
16
- <%= render 'constraints' %>
16
+ <%= render blacklight_config.view_config(document_index_view_type).constraints_component.new(search_state: search_state) %>
17
17
  <% end %>
18
18
 
19
- <%= render 'search_header' %>
19
+ <%= render blacklight_config.view_config(document_index_view_type).search_header_component.new %>
20
20
 
21
- <h2 class="sr-only visually-hidden"><%= t('blacklight.search.search_results') %></h2>
21
+ <h2 class="visually-hidden"><%= t('blacklight.search.search_results') %></h2>
22
22
 
23
23
  <%- if @response.empty? %>
24
24
  <%= render "zero_results" %>
@@ -1 +1 @@
1
- <h1 class="sr-only visually-hidden top-content-title"><%= t('blacklight.search.header') %></h1>
1
+ <h1 class="visually-hidden top-content-title"><%= t('blacklight.search.header') %></h1>
@@ -1,4 +1,4 @@
1
- <div id="sortAndPerPage" class="sort-pagination d-md-flex justify-content-between" role="navigation" aria-label="<%= t('blacklight.search.per_page.aria_label')%>">
1
+ <div id="sortAndPerPage" class="sort-pagination pb-3 d-md-flex justify-content-between" role="navigation" aria-label="<%= t('blacklight.search.per_page.aria_label')%>">
2
2
  <%= render partial: "paginate_compact", object: @response if show_pagination? %>
3
3
  <%= render_results_collection_tools wrapping_class: "search-widgets" %>
4
4
  </div>
@@ -1,6 +1,7 @@
1
1
  <% if show_sort_and_per_page? %>
2
2
  <%= render(Blacklight::Response::SortComponent.new(
3
3
  choices: active_sort_fields.map { |key, config| [sort_field_label(config.key), key] },
4
+ classes: ['mx-1'],
4
5
  search_state: search_state,
5
6
  selected: current_sort_field&.key)) %>
6
7
  <% end %>
@@ -1,14 +1,14 @@
1
1
  <%= render Blacklight::System::ModalComponent.new do |component| %>
2
- <% component.with_title { facet_field_label(@facet.key) } %>
2
+ <% component.with_prefix do %>
3
+ <div class="facet-pagination top d-flex w-100 justify-content-between">
4
+ <%= render :partial=>'facet_pagination' %>
5
+ </div>
6
+ <% end %>
3
7
 
4
- <div class="facet-filters card card-body bg-light p-3 mb-3 border-0">
5
- <%= render Blacklight::Search::FacetSuggestInput.new(facet: @facet, presenter: @presenter) %>
6
- <%= render partial: 'facet_index_navigation' if @facet.index_range && @display_facet.index? %>
7
- </div>
8
+ <% component.with_title { facet_field_label(@facet.key) } %>
9
+ <%= render Blacklight::Search::FacetSuggestInput.new(facet: @facet, presenter: @presenter) %>
8
10
 
9
- <div class="facet-pagination top d-flex flex-wrap w-100 justify-content-between border-bottom pb-3 mb-3">
10
- <%= render :partial=>'facet_pagination' %>
11
- </div>
11
+ <%= render partial: 'facet_index_navigation' if @facet.index_range && @display_facet.index? %>
12
12
 
13
13
  <div class="facet-extended-list">
14
14
  <%= render Blacklight::FacetComponent.new(display_facet: @display_facet,
@@ -17,7 +17,7 @@
17
17
  </div>
18
18
 
19
19
  <% component.with_footer do %>
20
- <div class="facet-pagination bottom d-flex flex-wrap w-100 justify-content-between">
20
+ <div class="facet-pagination bottom flex-row justify-content-between">
21
21
  <%= render :partial=>'facet_pagination' %>
22
22
  </div>
23
23
  <% end %>
@@ -1,7 +1,6 @@
1
1
  <%= render 'show_main_content' %>
2
2
 
3
3
  <% content_for(:sidebar) do %>
4
- <% Blacklight.deprecation.silence do %>
5
- <%= render_document_sidebar_partial @document %>
6
- <% end %>
4
+ <% presenter = document_presenter(@document) %>
5
+ <%= render presenter.view_config.sidebar_component.new(presenter: presenter) %>
7
6
  <% end %>
@@ -11,7 +11,6 @@
11
11
  <%= paginator.render do -%>
12
12
  <ul class="pagination">
13
13
  <%= prev_page_tag %>
14
- <%= next_page_tag if Blacklight::Engine.config.blacklight.paginator[:next_button_position] == :before %>
15
14
  <% each_relevant_page do |page| -%>
16
15
  <% if page.left_outer? || page.right_outer? || page.inside_window? -%>
17
16
  <%= page_tag page %>
@@ -19,6 +18,6 @@
19
18
  <%= gap_tag %>
20
19
  <% end -%>
21
20
  <% end -%>
22
- <%= next_page_tag if Blacklight::Engine.config.blacklight.paginator[:next_button_position] == :after %>
21
+ <%= next_page_tag %>
23
22
  </ul>
24
23
  <% end -%>
@@ -12,15 +12,11 @@
12
12
  <%= opensearch_description_tag application_name, opensearch_catalog_url(format: 'xml') %>
13
13
  <%= favicon_link_tag %>
14
14
  <%= stylesheet_link_tag "application", media: "all", "data-turbo-track": "reload" %>
15
+
15
16
  <% if defined? Importmap %>
16
17
  <%= javascript_importmap_tags %>
17
- <% elsif defined? Propshaft %>
18
- <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
19
18
  <% else %>
20
19
  <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
21
- <script type="module">
22
- import githubAutoCompleteElement from 'https://cdn.skypack.dev/@github/auto-complete-element';
23
- </script>
24
20
  <% end %>
25
21
 
26
22
  <%= csrf_meta_tags %>
@@ -31,9 +27,9 @@
31
27
  <%= content_for(:skip_links) %>
32
28
  <% end %>
33
29
 
34
- <%= render partial: 'shared/header_navbar' %>
30
+ <%= render blacklight_config.header_component.new(blacklight_config: blacklight_config) %>
35
31
 
36
- <main id="main-container" class="<%= container_classes %>" role="main" aria-label="<%= t('blacklight.main.aria.main_container') %>">
32
+ <main id="main-container" class="<%= container_classes %>" aria-label="<%= t('blacklight.main.aria.main_container') %>">
37
33
  <%= content_for(:container_header) %>
38
34
 
39
35
  <%= render partial: 'shared/flash_msg', layout: 'shared/flash_messages' %>
@@ -7,9 +7,7 @@
7
7
  <% else %>
8
8
  <%= link_to t('blacklight.search_history.clear.action_title'),
9
9
  blacklight.clear_search_history_path,
10
- method: :delete, # for rails-ujs
11
10
  data: {
12
- confirm: t('blacklight.search_history.clear.action_confirm'), # for rails-ujs
13
11
  turbo_confirm: t('blacklight.search_history.clear.action_confirm'),
14
12
  turbo_method: :delete
15
13
  },
data/blacklight.gemspec CHANGED
@@ -23,19 +23,19 @@ Gem::Specification.new do |s|
23
23
  s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  s.require_paths = ["lib"]
25
25
 
26
- s.required_ruby_version = '>= 2.7'
26
+ s.required_ruby_version = '>= 3.1'
27
27
 
28
- s.add_dependency "rails", '>= 6.1', '< 9'
28
+ s.add_dependency "rails", '>= 7.0', '< 9'
29
29
  s.add_dependency "globalid"
30
30
  s.add_dependency "jbuilder", '~> 2.7'
31
31
  s.add_dependency "kaminari", ">= 0.15" # the pagination (page 1,2,3, etc..) of our search results
32
32
  s.add_dependency "i18n", '>= 1.7.0' # added named parameters
33
33
  s.add_dependency "ostruct", '>= 0.3.2'
34
- s.add_dependency "view_component", '>= 2.74', '< 4'
34
+ s.add_dependency "view_component", '~> 3.9'
35
35
  s.add_dependency "zeitwerk"
36
36
 
37
37
  s.add_development_dependency "rsolr", ">= 1.0.6", "< 3" # Library for interacting with rSolr.
38
- s.add_development_dependency "rspec-rails", ">= 6.1", "< 8"
38
+ s.add_development_dependency "rspec-rails", "~> 7.0"
39
39
  s.add_development_dependency "rspec-collection_matchers", ">= 1.0"
40
40
  s.add_development_dependency 'axe-core-rspec'
41
41
  s.add_development_dependency "capybara", '~> 3'
data/config/importmap.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- pin_all_from File.expand_path("../app/javascript/blacklight", __dir__), under: "blacklight"
3
+ pin_all_from File.expand_path("../app/javascript/blacklight-frontend", __dir__), under: "blacklight-frontend"