blacklight 7.13.2 → 7.15.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +23 -3
  3. data/README.md +0 -2
  4. data/VERSION +1 -1
  5. data/app/assets/javascripts/blacklight/blacklight.js +4 -2
  6. data/app/assets/stylesheets/blacklight/_header.scss +0 -5
  7. data/app/assets/stylesheets/blacklight/_icons.scss +5 -1
  8. data/app/assets/stylesheets/blacklight/blacklight_defaults.scss +5 -1
  9. data/app/components/blacklight/advanced_search_form_component.html.erb +46 -0
  10. data/app/components/blacklight/advanced_search_form_component.rb +75 -0
  11. data/app/components/blacklight/constraint_component.html.erb +1 -1
  12. data/app/components/blacklight/constraint_layout_component.html.erb +1 -1
  13. data/app/components/blacklight/constraints_component.rb +42 -17
  14. data/app/components/blacklight/document/thumbnail_component.html.erb +2 -2
  15. data/app/components/blacklight/document/thumbnail_component.rb +5 -2
  16. data/app/components/blacklight/document_component.rb +7 -2
  17. data/app/components/blacklight/document_metadata_component.rb +1 -1
  18. data/app/components/blacklight/facet_field_checkboxes_component.html.erb +23 -0
  19. data/app/components/blacklight/facet_field_checkboxes_component.rb +24 -0
  20. data/app/components/blacklight/facet_field_inclusive_constraint_component.html.erb +6 -0
  21. data/app/components/blacklight/facet_field_inclusive_constraint_component.rb +29 -0
  22. data/app/components/blacklight/facet_field_list_component.html.erb +1 -0
  23. data/app/components/blacklight/facet_field_pagination_component.rb +1 -1
  24. data/app/components/blacklight/facet_item_component.rb +4 -2
  25. data/app/components/blacklight/hidden_search_state_component.rb +54 -0
  26. data/app/components/blacklight/search_bar_component.html.erb +4 -0
  27. data/app/components/blacklight/search_bar_component.rb +4 -2
  28. data/app/controllers/concerns/blacklight/bookmarks.rb +1 -1
  29. data/app/controllers/concerns/blacklight/catalog.rb +6 -0
  30. data/app/helpers/blacklight/component_helper_behavior.rb +1 -1
  31. data/app/helpers/blacklight/configuration_helper_behavior.rb +2 -2
  32. data/app/helpers/blacklight/facets_helper_behavior.rb +1 -1
  33. data/app/helpers/blacklight/hash_as_hidden_fields_helper_behavior.rb +2 -38
  34. data/app/helpers/blacklight/icon_helper_behavior.rb +1 -1
  35. data/app/helpers/blacklight/render_constraints_helper_behavior.rb +2 -2
  36. data/app/javascript/blacklight/button_focus.js +1 -0
  37. data/app/javascript/blacklight/modal.js +10 -4
  38. data/app/models/concerns/blacklight/suggest/response.rb +1 -1
  39. data/app/presenters/blacklight/clause_presenter.rb +37 -0
  40. data/app/presenters/blacklight/document_presenter.rb +5 -1
  41. data/app/presenters/blacklight/facet_field_presenter.rb +4 -0
  42. data/app/presenters/blacklight/facet_grouped_item_presenter.rb +45 -0
  43. data/app/presenters/blacklight/facet_item_presenter.rb +32 -20
  44. data/app/presenters/blacklight/field_presenter.rb +1 -1
  45. data/app/presenters/blacklight/inclusive_facet_item_presenter.rb +16 -0
  46. data/app/presenters/blacklight/rendering/helper_method.rb +4 -4
  47. data/app/presenters/blacklight/search_bar_presenter.rb +4 -0
  48. data/app/views/bookmarks/_tools.html.erb +1 -1
  49. data/app/views/catalog/_advanced_search_form.html.erb +7 -0
  50. data/app/views/catalog/_advanced_search_help.html.erb +24 -0
  51. data/app/views/catalog/_search_form.html.erb +1 -0
  52. data/app/views/catalog/_zero_results.html.erb +1 -1
  53. data/app/views/catalog/advanced_search.html.erb +17 -0
  54. data/blacklight.gemspec +5 -4
  55. data/config/i18n-tasks.yml +1 -0
  56. data/config/locales/blacklight.en.yml +17 -0
  57. data/lib/blacklight/configuration.rb +2 -1
  58. data/lib/blacklight/configuration/field.rb +1 -1
  59. data/lib/blacklight/configuration/sort_field.rb +1 -1
  60. data/lib/blacklight/open_struct_with_hash_access.rb +18 -1
  61. data/lib/blacklight/routes/searchable.rb +1 -0
  62. data/lib/blacklight/search_builder.rb +2 -0
  63. data/lib/blacklight/search_state.rb +5 -1
  64. data/lib/blacklight/search_state/filter_field.rb +17 -7
  65. data/lib/blacklight/solr/repository.rb +11 -2
  66. data/lib/blacklight/solr/search_builder_behavior.rb +87 -23
  67. data/package.json +1 -1
  68. data/spec/components/blacklight/advanced_search_form_component_spec.rb +51 -0
  69. data/spec/components/blacklight/constraint_layout_component_spec.rb +1 -1
  70. data/spec/components/blacklight/document_component_spec.rb +17 -0
  71. data/spec/components/blacklight/facet_field_checkboxes_component_spec.rb +55 -0
  72. data/spec/components/blacklight/facet_field_list_component_spec.rb +39 -4
  73. data/spec/components/blacklight/hidden_search_state_component_spec.rb +24 -0
  74. data/spec/controllers/catalog_controller_spec.rb +9 -0
  75. data/spec/features/advanced_search_spec.rb +67 -0
  76. data/spec/features/bookmarks_spec.rb +1 -9
  77. data/spec/features/facets_spec.rb +2 -17
  78. data/spec/features/search_filters_spec.rb +0 -20
  79. data/spec/helpers/blacklight/hash_as_hidden_fields_behavior_spec.rb +1 -0
  80. data/spec/helpers/blacklight/url_helper_behavior_spec.rb +1 -0
  81. data/spec/lib/blacklight/open_struct_with_hash_access_spec.rb +8 -0
  82. data/spec/lib/blacklight/search_state/filter_field_spec.rb +65 -0
  83. data/spec/models/blacklight/solr/repository_spec.rb +12 -0
  84. data/spec/models/blacklight/solr/response/facets_spec.rb +1 -1
  85. data/spec/models/blacklight/solr/search_builder_spec.rb +28 -0
  86. data/spec/presenters/blacklight/clause_presenter_spec.rb +34 -0
  87. data/spec/presenters/blacklight/document_presenter_spec.rb +13 -0
  88. data/spec/presenters/blacklight/facet_grouped_item_presenter_spec.rb +41 -0
  89. data/spec/spec_helper.rb +8 -3
  90. data/spec/test_app_templates/Gemfile.extra +1 -1
  91. data/spec/views/catalog/_document.html.erb_spec.rb +1 -0
  92. data/spec/views/catalog/_thumbnail.html.erb_spec.rb +2 -0
  93. metadata +66 -27
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ class FacetFieldCheckboxesComponent < ::ViewComponent::Base
5
+ def initialize(facet_field:, layout: nil)
6
+ @facet_field = facet_field
7
+ @layout = layout == false ? FacetFieldNoLayoutComponent : Blacklight::FacetFieldComponent
8
+ end
9
+
10
+ def render?
11
+ presenters.any?
12
+ end
13
+
14
+ def presenters
15
+ return [] unless @facet_field.paginator
16
+
17
+ return to_enum(:presenters) unless block_given?
18
+
19
+ @facet_field.paginator.items.each do |item|
20
+ yield Blacklight::FacetItemPresenter.new(item, @facet_field.facet_field, @view_context, @facet_field.key, @facet_field.search_state)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,6 @@
1
+ <div class="inclusive_or card card-body bg-light mb-3">
2
+ <h5><%= t('blacklight.advanced_search.any_of') %></h5>
3
+ <ul class="list-unstyled facet-values">
4
+ <%= @view_context.render(Blacklight::FacetItemComponent.with_collection(presenters.to_a)) %>
5
+ </ul>
6
+ </div>
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ class FacetFieldInclusiveConstraintComponent < ::ViewComponent::Base
5
+ with_collection_parameter :facet_field
6
+
7
+ def initialize(facet_field:, values: nil)
8
+ @facet_field = facet_field
9
+ @values = values
10
+ end
11
+
12
+ def values
13
+ @values ||= @facet_field.values.find { |v| v.is_a? Array }
14
+ @values || []
15
+ end
16
+
17
+ def render?
18
+ values.present?
19
+ end
20
+
21
+ def presenters
22
+ return to_enum(:presenters) unless block_given?
23
+
24
+ values.each do |item|
25
+ yield Blacklight::FacetGroupedItemPresenter.new(values, item, @facet_field.facet_field, @view_context, @facet_field.key, @facet_field.search_state)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -3,6 +3,7 @@
3
3
  <%= @facet_field.label %>
4
4
  <% end %>
5
5
  <% component.with(:body) do %>
6
+ <%= @view_context.render(Blacklight::FacetFieldInclusiveConstraintComponent.new(facet_field: @facet_field)) %>
6
7
  <ul class="facet-values list-unstyled">
7
8
  <%= render_facet_limit_list @facet_field.paginator, @facet_field.key %>
8
9
  </ul>
@@ -7,7 +7,7 @@ module Blacklight
7
7
  end
8
8
 
9
9
  def sort_facet_url(sort)
10
- @facet_field.paginator.params_for_resort_url(sort, @facet_fieldsearch_state.to_h)
10
+ @facet_field.paginator.params_for_resort_url(sort, @facet_field.search_state.to_h)
11
11
  end
12
12
 
13
13
  def param_name
@@ -86,8 +86,8 @@ module Blacklight
86
86
  tag.span(@label, class: "selected") +
87
87
  # remove link
88
88
  link_to(@href, class: "remove") do
89
- tag.span('✖', class: "remove-icon") +
90
- tag.span('[remove]', class: 'sr-only')
89
+ tag.span('✖', class: "remove-icon", aria: { hidden: true }) +
90
+ tag.span(@view_context.t(:'blacklight.search.facets.selected.remove'), class: 'sr-only')
91
91
  end
92
92
  end + render_facet_count(classes: ["selected"])
93
93
  end
@@ -103,6 +103,8 @@ module Blacklight
103
103
  def render_facet_count(options = {})
104
104
  return @view_context.render_facet_count(@hits, options) unless @view_context.method(:render_facet_count).owner == Blacklight::FacetsHelperBehavior || explicit_component_configuration?
105
105
 
106
+ return '' if @hits.blank?
107
+
106
108
  classes = (options[:classes] || []) << "facet-count"
107
109
  tag.span(t('blacklight.search.facets.count', number: number_with_delimiter(@hits)), class: classes)
108
110
  end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ # Writes out zero or more <input type="hidden"> elements, completely
5
+ # representing a hash passed in using Rails-style request parameters
6
+ # for hashes nested with arrays and other hashes.
7
+ class HiddenSearchStateComponent < ::ViewComponent::Base
8
+ # @param [Hash] hash
9
+ def initialize(params:)
10
+ Deprecation.warn(self, "Passing page as a parameter to HiddenSearchStateComponent is deprecated and will not be supported in Blacklight 8") if params.key?(:page)
11
+ @params = params.except(:utf8)
12
+ end
13
+
14
+ def call
15
+ hidden_fields = []
16
+ flatten_hash(@params).each do |name, value|
17
+ value = Array.wrap(value)
18
+ value.each do |v|
19
+ hidden_fields << hidden_field_tag(name, v.to_s, id: nil)
20
+ end
21
+ end
22
+
23
+ safe_join(hidden_fields, "\n")
24
+ end
25
+
26
+ private
27
+
28
+ def flatten_hash(hash = params, ancestor_names = [])
29
+ flat_hash = {}
30
+ hash.each do |k, v|
31
+ names = Array.new(ancestor_names)
32
+ names << k
33
+ if v.is_a?(Hash)
34
+ flat_hash.merge!(flatten_hash(v, names))
35
+ else
36
+ key = flat_hash_key(names)
37
+ key += "[]" if v.is_a?(Array)
38
+ flat_hash[key] = v
39
+ end
40
+ end
41
+
42
+ flat_hash
43
+ end
44
+
45
+ def flat_hash_key(names)
46
+ names = Array.new(names)
47
+ name = names.shift.to_s.dup
48
+ names.each do |n|
49
+ name << "[#{n}]"
50
+ end
51
+ name
52
+ end
53
+ end
54
+ end
@@ -29,3 +29,7 @@
29
29
  </span>
30
30
  </div>
31
31
  <% end %>
32
+
33
+ <% if presenter.advanced_search_enabled? %>
34
+ <%= link_to t('blacklight.advanced_search.more_options'), @advanced_search_url, class: 'advanced_search btn btn-secondary'%>
35
+ <% end %>
@@ -6,12 +6,14 @@ module Blacklight
6
6
 
7
7
  # rubocop:disable Metrics/ParameterLists
8
8
  def initialize(
9
- url:, params:, classes: ['search-query-form'], presenter: nil,
10
- prefix: '', method: 'GET', q: nil, query_param: :q,
9
+ url:, advanced_search_url: nil, params:,
10
+ classes: ['search-query-form'], presenter: nil, prefix: '',
11
+ method: 'GET', q: nil, query_param: :q,
11
12
  search_field: nil, search_fields: [], autocomplete_path: nil,
12
13
  autofocus: nil, i18n: { scope: 'blacklight.search.form' }
13
14
  )
14
15
  @url = url
16
+ @advanced_search_url = advanced_search_url
15
17
  @q = q || params[:q]
16
18
  @query_param = query_param
17
19
  @search_field = search_field || params[:search_field]
@@ -25,7 +25,7 @@ module Blacklight::Bookmarks
25
25
  def action_documents
26
26
  bookmarks = token_or_current_or_guest_user.bookmarks
27
27
  bookmark_ids = bookmarks.collect { |b| b.document_id.to_s }
28
- search_service.fetch(bookmark_ids)
28
+ search_service.fetch(bookmark_ids, rows: bookmark_ids.count)
29
29
  end
30
30
 
31
31
  def action_success_redirect_path
@@ -56,6 +56,12 @@ module Blacklight::Catalog
56
56
  end
57
57
  end
58
58
 
59
+ def advanced_search
60
+ empty_service = search_service_class.new(config: blacklight_config, user_params: {}, **search_service_context)
61
+
62
+ (@response, _deprecated_document_list) = empty_service.search_results
63
+ end
64
+
59
65
  # get a single document from the index
60
66
  def raw
61
67
  raise(ActionController::RoutingError, 'Not Found') unless blacklight_config.raw_endpoint.enabled
@@ -10,7 +10,7 @@ module Blacklight
10
10
  deprecation_deprecate :document_action_label
11
11
 
12
12
  # @deprecated
13
- def document_action_path action_opts, url_opts = nil
13
+ def document_action_path action_opts, url_opts = {}
14
14
  if action_opts.path
15
15
  send(action_opts.path, url_opts)
16
16
  elsif url_opts[:id].class.respond_to?(:model_name)
@@ -189,7 +189,7 @@ module Blacklight::ConfigurationHelperBehavior
189
189
 
190
190
  field = fields.first if document.nil?
191
191
  field ||= fields.find { |f| document.has? f }
192
- field &&= field.try(:to_sym)
192
+ field &&= field&.to_sym
193
193
 
194
194
  field
195
195
  end
@@ -198,7 +198,7 @@ module Blacklight::ConfigurationHelperBehavior
198
198
  ##
199
199
  # Default sort field
200
200
  def default_sort_field
201
- (active_sort_fields.find { |_k, config| config.respond_to?(:default) && config.default } || active_sort_fields.first).try(:last)
201
+ (active_sort_fields.find { |_k, config| config.respond_to?(:default) && config.default } || active_sort_fields.first)&.last
202
202
  end
203
203
 
204
204
  ##
@@ -180,7 +180,7 @@ module Blacklight::FacetsHelperBehavior
180
180
  # @return [String]
181
181
  def facet_partial_name(display_facet = nil)
182
182
  config = facet_configuration_for_field(display_facet.name)
183
- name = config.try(:partial)
183
+ name = config.partial
184
184
  name ||= "facet_pivot" if config.pivot
185
185
  name || "facet_limit"
186
186
  end
@@ -21,43 +21,7 @@ module Blacklight::HashAsHiddenFieldsHelperBehavior
21
21
  # @param [Hash] hash
22
22
  # @return [String]
23
23
  def render_hash_as_hidden_fields(hash)
24
- hidden_fields = []
25
- flatten_hash(hash).each do |name, value|
26
- value = Array.wrap(value)
27
- value.each do |v|
28
- hidden_fields << hidden_field_tag(name, v.to_s, id: nil)
29
- end
30
- end
31
-
32
- safe_join(hidden_fields, "\n")
33
- end
34
- deprecation_deprecate render_hash_as_hidden_fields: 'Moving to a private method of Blacklight::SearchBarComponent'
35
-
36
- private
37
-
38
- def flatten_hash(hash = params, ancestor_names = [])
39
- flat_hash = {}
40
- hash.each do |k, v|
41
- names = Array.new(ancestor_names)
42
- names << k
43
- if v.is_a?(Hash)
44
- flat_hash.merge!(flatten_hash(v, names))
45
- else
46
- key = flat_hash_key(names)
47
- key += "[]" if v.is_a?(Array)
48
- flat_hash[key] = v
49
- end
50
- end
51
-
52
- flat_hash
53
- end
54
-
55
- def flat_hash_key(names)
56
- names = Array.new(names)
57
- name = names.shift.to_s.dup
58
- names.each do |n|
59
- name << "[#{n}]"
60
- end
61
- name
24
+ render Blacklight::HiddenSearchStateComponent.new(params: hash)
62
25
  end
26
+ deprecation_deprecate render_hash_as_hidden_fields: 'Use Blacklight::HiddenSearchStateComponent instead'
63
27
  end
@@ -12,7 +12,7 @@ module Blacklight::IconHelperBehavior
12
12
  def blacklight_icon(icon_name, options = {})
13
13
  Rails.cache.fetch([:blacklight_icons, icon_name, options]) do
14
14
  icon = Blacklight::Icon.new(icon_name, **options)
15
- tag.span(icon.svg.html_safe, icon.options)
15
+ tag.span(icon.svg.html_safe, **icon.options)
16
16
  end
17
17
  end
18
18
  end
@@ -88,8 +88,8 @@ module Blacklight::RenderConstraintsHelperBehavior
88
88
  return "".html_safe if search_state.filter_params.blank?
89
89
 
90
90
  Deprecation.silence(Blacklight::RenderConstraintsHelperBehavior) do
91
- safe_join(search_state.filter_params.each_pair.map do |facet, values|
92
- render_filter_element(facet, values, search_state)
91
+ safe_join(search_state.filters.map do |field|
92
+ render_filter_element(field.key, field.values, search_state)
93
93
  end, "\n")
94
94
  end
95
95
  end
@@ -1,6 +1,7 @@
1
1
  Blacklight.onLoad(function() {
2
2
  // Button clicks should change focus. As of 10/3/19, Firefox for Mac and
3
3
  // Safari both do not set focus to a button on button click.
4
+ // See https://zellwk.com/blog/inconsistent-button-behavior/ for background information
4
5
  document.querySelectorAll('button.collapse-toggle').forEach((button) => {
5
6
  button.addEventListener('click', () => {
6
7
  event.target.focus();
@@ -101,12 +101,18 @@ Blacklight.modal.modalCloseSelector = '[data-blacklight-modal~=close]';
101
101
  // Called on fatal failure of ajax load, function returns content
102
102
  // to show to user in modal. Right now called only for extreme
103
103
  // network errors.
104
- Blacklight.modal.onFailure = function(data) {
105
- var contents = '<div class="modal-header">' +
106
- '<div class="modal-title">Network Error</div>' +
104
+ Blacklight.modal.onFailure = function(jqXHR, textStatus, errorThrown) {
105
+ console.error('Server error:', this.url, jqXHR.status, errorThrown);
106
+
107
+ var contents = '<div class="modal-header">' +
108
+ '<div class="modal-title">There was a problem with your request.</div>' +
107
109
  '<button type="button" class="blacklight-modal-close close" data-dismiss="modal" aria-label="Close">' +
108
110
  ' <span aria-hidden="true">&times;</span>' +
109
- '</button>';
111
+ '</button></div>' +
112
+ ' <div class="modal-body"><p>Expected a successful response from the server, but got an error</p>' +
113
+ '<pre>' +
114
+ this.type + ' ' + this.url + "\n" + jqXHR.status + ': ' + errorThrown +
115
+ '</pre></div>';
110
116
  $(Blacklight.modal.modalSelector).find('.modal-content').html(contents);
111
117
  $(Blacklight.modal.modalSelector).modal('show');
112
118
  }
@@ -22,7 +22,7 @@ module Blacklight
22
22
  # present
23
23
  # @return [Array]
24
24
  def suggestions
25
- (response.try(:[], suggest_path).try(:[], suggester_name).try(:[], request_params[:q]).try(:[], 'suggestions') || []).uniq
25
+ (response.dig(suggest_path, suggester_name, request_params[:q], 'suggestions') || []).uniq
26
26
  end
27
27
  end
28
28
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ class ClausePresenter
5
+ attr_reader :key, :user_parameters, :field_config, :view_context, :search_state
6
+
7
+ def initialize(key, user_parameters, field_config, view_context, search_state = view_context.search_state)
8
+ @key = key
9
+ @user_parameters = user_parameters
10
+ @field_config = field_config
11
+ @view_context = view_context
12
+ @search_state = search_state
13
+ end
14
+
15
+ def field_label
16
+ field_config.display_label('search')
17
+ end
18
+
19
+ ##
20
+ # Get the displayable version of a facet's value
21
+ #
22
+ # @return [String]
23
+ def label
24
+ user_parameters[:query]
25
+ end
26
+
27
+ def remove_href(path = search_state)
28
+ view_context.search_action_path(path.reset_search(clause: path.clause_params.except(key)))
29
+ end
30
+
31
+ private
32
+
33
+ def facet_field_presenter
34
+ @facet_field_presenter ||= view_context.facet_field_presenter(facet_config, {})
35
+ end
36
+ end
37
+ end
@@ -97,8 +97,12 @@ module Blacklight
97
97
  field_presenter(field_config, options).render
98
98
  end
99
99
 
100
+ def thumbnail_presenter_class
101
+ view_config.thumbnail_presenter || thumbnail_presenter
102
+ end
103
+
100
104
  def thumbnail
101
- @thumbnail ||= thumbnail_presenter.new(document, view_context, view_config)
105
+ @thumbnail ||= thumbnail_presenter_class.new(document, view_context, view_config)
102
106
  end
103
107
 
104
108
  ##
@@ -40,6 +40,10 @@ module Blacklight
40
40
  view_context.facet_field_label(key)
41
41
  end
42
42
 
43
+ def values
44
+ search_state&.filter(facet_field)&.values || []
45
+ end
46
+
43
47
  # @private
44
48
  # @deprecated
45
49
  def html_id
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ class FacetGroupedItemPresenter < Blacklight::FacetItemPresenter
5
+ attr_reader :group
6
+
7
+ delegate :key, to: :facet_config
8
+
9
+ def initialize(group, facet_item, facet_config, view_context, facet_field, search_state = view_context.search_state)
10
+ @group = group
11
+ @facet_item = facet_item
12
+ @facet_config = facet_config
13
+ @view_context = view_context
14
+ @facet_field = facet_field
15
+ @search_state = search_state
16
+ end
17
+
18
+ ##
19
+ # Check if the query parameters have the given facet field with the
20
+ # given value.
21
+ def selected?
22
+ group.include?(facet_item)
23
+ end
24
+
25
+ # @private
26
+ def remove_href(path = search_state)
27
+ new_state = path.filter(facet_config).remove(group)
28
+ new_state = new_state.filter(facet_config).add(group - [facet_item])
29
+
30
+ view_context.search_action_path(new_state)
31
+ end
32
+
33
+ # @private
34
+ def add_href(_path_options = {})
35
+ if facet_config.url_method
36
+ return view_context.public_send(facet_config.url_method, facet_config.key, facet_item)
37
+ end
38
+
39
+ new_state = search_state.filter(facet_config).remove(@group)
40
+ new_state = new_state.filter(facet_config).add(@group + [facet_item])
41
+
42
+ view_context.search_action_path(new_state)
43
+ end
44
+ end
45
+ end